Update to latest trace-viewer

Change-Id: I01d0c0115cee7c838f0a66eb1f5c76756480e158
diff --git a/UPSTREAM_REVISION b/UPSTREAM_REVISION
index dd73238..fcec727 100644
--- a/UPSTREAM_REVISION
+++ b/UPSTREAM_REVISION
@@ -1 +1 @@
-bcdf739e4b5aaaafa6e2b896dce6b0866698d2f3
+98bb819e78ccfd8db0e9c08c4bf91d1fab162ab8
diff --git a/prefix.html b/prefix.html
index 887293a..1419f30 100644
--- a/prefix.html
+++ b/prefix.html
@@ -21,12 +21,12 @@
 {{SYSTRACE_TRACE_VIEWER_HTML}}
 <script language="javascript">
 document.addEventListener('DOMContentLoaded', function() {
-  var traceViewerEl = new tv.TraceViewer();
+  var traceViewerEl = new tr.TraceViewer();
   traceViewerEl.viewTitle = 'Android System Trace';
   var viewInsertionPt = document.body.querySelector('#trace-viewer-insertion-pt');
   viewInsertionPt.parentElement.replaceChild(traceViewerEl, viewInsertionPt);
 
-  var m = new tv.c.TraceModel();
+  var m = new tr.Model();
 
   var traceDataEls = document.body.querySelectorAll('.trace-data');
   var traces = [];
@@ -46,8 +46,8 @@
         traceViewerEl.timeline.focusElement = traceViewerEl;
     },
     function(err) {
-      var overlay = new tv.ui.Overlay();
-      overlay.textContent = tv.normalizeException(err).message;
+      var overlay = new tr.b.ui.Overlay();
+      overlay.textContent = tr.b.normalizeException(err).message;
       overlay.title = 'Import error';
       overlay.visible = true;
     });
diff --git a/systrace_trace_viewer.html b/systrace_trace_viewer.html
index bad4d27..bbf6fb3 100644
--- a/systrace_trace_viewer.html
+++ b/systrace_trace_viewer.html
@@ -100,7 +100,7 @@
 </overlay-frame>
 </overlay-vertical-centering-container>
 </overlay-mask>
-</template><polymer-element name="tv-b-dropdown">
+</template><polymer-element name="tr-b-ui-dropdown">
 <template>
 <style>
     :host {
@@ -249,9 +249,9 @@
 </tabs-content-container>
 </template>
 
-</polymer-element><polymer-element name="tracing-analysis-sub-view" constructor="TracingAnalysisSubView">
+</polymer-element><polymer-element name="tr-c-a-sub-view">
 
-</polymer-element><polymer-element name="tv-c-a-time-span">
+</polymer-element><polymer-element name="tr-b-u-time-duration-span">
 <template>
 <style>
     :host {
@@ -268,11 +268,11 @@
 <span id="warning" style="display:none">&#9888;</span>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-time-stamp">
+</polymer-element><polymer-element name="tr-b-u-time-stamp-span">
 <template>
 </template>
 
-</polymer-element><polymer-element name="tv-c-analysis-link" is="a">
+</polymer-element><polymer-element name="tr-c-a-analysis-link" is="a">
 <template>
 <style>
     :host {
@@ -292,29 +292,7 @@
 <content></content>
 </template>
 
-</polymer-element><polymer-element name="tv-c-analysis-generic-object-view" is="HTMLUnknownElement">
-<template>
-<style>
-    :host {
-      display: block;
-      font-family: monospace;
-    }
-    </style>
-<div id="content">
-</div>
-</template>
-
-</polymer-element>
-<polymer-element name="tv-c-analysis-generic-object-view-with-label" is="HTMLUnknownElement">
-<template>
-<style>
-    :host {
-      display: block;
-    }
-    </style>
-</template>
-
-</polymer-element><polymer-element name="tv-c-a-stack-frame">
+</polymer-element><polymer-element name="tr-b-u-size-in-bytes-span">
 <template>
 <style>
     :host {
@@ -323,30 +301,10 @@
       align-items: center;
     }
     </style>
-<tv-c-analysis-generic-object-view id="ov">
-</tv-c-analysis-generic-object-view>
+<span id="content"></span>
 </template>
 
-</polymer-element><polymer-element name="tracing-analysis-toggle-container" constructor="TracingAnalysisToggleContainer">
-<template>
-<style>
-      :host(:[visible]) {
-        display: flex;
-      }
-
-      :host(:not([visible])) {
-        display: none;
-      }
-
-      ::content > * {
-        flex: 0 1 auto;
-      }
-
-    </style>
-<content></content>
-</template>
-
-</polymer-element><polymer-element name="tracing-analysis-nested-table">
+</polymer-element><polymer-element name="tr-b-ui-table">
 <template>
 <style>
       :host {
@@ -467,7 +425,7 @@
 </template>
 
 </polymer-element>
-<polymer-element name="tracing-analysis-header-cell" constructor="TracingAnalysisHeaderCell" on-tap="onTap_">
+<polymer-element name="tr-b-ui-table-header-cell" on-tap="onTap_">
 <template>
 <style>
     :host {
@@ -493,7 +451,42 @@
 <span id="title"></span><side-element id="side"></side-element>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-single-event-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-generic-object-view" is="HTMLUnknownElement">
+<template>
+<style>
+    :host {
+      display: block;
+      font-family: monospace;
+    }
+    </style>
+<div id="content">
+</div>
+</template>
+
+</polymer-element>
+<polymer-element name="tr-c-a-generic-object-view-with-label" is="HTMLUnknownElement">
+<template>
+<style>
+    :host {
+      display: block;
+    }
+    </style>
+</template>
+
+</polymer-element><polymer-element name="tr-c-a-stack-frame">
+<template>
+<style>
+    :host {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+    }
+    </style>
+<tr-c-a-generic-object-view id="ov">
+</tr-c-a-generic-object-view>
+</template>
+
+</polymer-element><polymer-element name="tr-c-a-single-event-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -505,11 +498,11 @@
       align-self: stretch;
     }
     </style>
-<tracing-analysis-nested-table id="table">
-</tracing-analysis-nested-table>
+<tr-b-ui-table id="table">
+</tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-related-flows">
+</polymer-element><polymer-element name="tr-c-a-related-events">
 <template>
 <style>
     :host {
@@ -521,30 +514,30 @@
       align-self: stretch;
     }
     </style>
-<tracing-analysis-nested-table id="table"></tracing-analysis-nested-table>
+<tr-b-ui-table id="table"></tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-single-thread-slice-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-thread-slice-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
       display: flex;
       flex-direction: row;
     }
-    #flows {
+    #events {
       display: flex;
       flex-direction: column;
     }
 
     </style>
-<tv-c-a-single-event-sub-view id="content"></tv-c-a-single-event-sub-view>
-<div id="flows">
-<tv-c-a-related-flows id="rflows">
-</tv-c-a-related-flows>
+<tr-c-a-single-event-sub-view id="content"></tr-c-a-single-event-sub-view>
+<div id="events">
+<tr-c-a-related-events id="relatedEvents">
+</tr-c-a-related-events>
 </div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-selection-summary-table">
+</polymer-element><polymer-element name="tr-c-a-selection-summary-table">
 <template>
 <style>
     :host {
@@ -555,11 +548,11 @@
       align-self: stretch;
     }
     </style>
-<tracing-analysis-nested-table id="table">
-</tracing-analysis-nested-table>
+<tr-b-ui-table id="table">
+</tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-multi-event-summary-table">
+</polymer-element><polymer-element name="tr-c-a-multi-event-summary-table">
 <template>
 <style>
     :host {
@@ -570,11 +563,11 @@
       align-self: stretch;
     }
     </style>
-<tracing-analysis-nested-table id="table">
-</tracing-analysis-nested-table>
+<tr-b-ui-table id="table">
+</tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-multi-event-details-table">
+</polymer-element><polymer-element name="tr-c-a-multi-event-details-table">
 <template>
 <style>
     :host {
@@ -594,13 +587,13 @@
       font-size: 12px;
     }
     </style>
-<tracing-analysis-nested-table id="titletable">
-</tracing-analysis-nested-table>
-<tracing-analysis-nested-table id="table">
-</tracing-analysis-nested-table>
+<tr-b-ui-table id="titletable">
+</tr-b-ui-table>
+<tr-b-ui-table id="table">
+</tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-multi-event-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-event-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -617,11 +610,11 @@
       flex: 0 0 auto;
       align-self: stretch;
     }
-    tv-c-a-multi-event-summary-table {
+    tr-c-a-multi-event-summary-table {
       border-bottom: 1px solid #aaa;
     }
 
-    tv-c-a-selection-summary-table  {
+    tr-c-a-selection-summary-table  {
       margin-top: 1.25em;
       border-top: 1px solid #aaa;
       background-color: #eee;
@@ -633,7 +626,7 @@
 <div id="content"></div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-multi-thread-slice-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-thread-slice-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -643,26 +636,26 @@
       display: flex;
       flex: 1 1 auto;
     }
-    #content > tv-c-a-related-flows {
+    #content > tr-c-a-related-events {
       margin-left: 8px;
     }
     </style>
 <div id="content"></div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-single-async-slice-sub-view" extends="tv-c-a-single-event-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-async-slice-sub-view" extends="tr-c-a-single-event-sub-view">
 
-</polymer-element><polymer-element name="tv-c-a-multi-async-slice-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-async-slice-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
       display: flex;
     }
     </style>
-<tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+<tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-cpu-slice-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-cpu-slice-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     table {
@@ -713,14 +706,14 @@
 <tr>
 <td>Args:</td>
 <td>
-<tv-c-analysis-generic-object-view id="args">
-</tv-c-analysis-generic-object-view>
+<tr-c-a-generic-object-view id="args">
+</tr-c-a-generic-object-view>
 </td>
 </tr>
 </table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-multi-cpu-slice-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-cpu-slice-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -730,10 +723,10 @@
       flex: 1 1 auto;
     }
     </style>
-<tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+<tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-thread-time-slice-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-thread-time-slice-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     table {
@@ -794,7 +787,7 @@
 </table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-multi-thread-time-slice-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-thread-time-slice-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -804,10 +797,10 @@
       flex: 1 1 auto;
     }
     </style>
-<tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+<tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-instant-event-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-instant-event-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -817,7 +810,7 @@
 <div id="content"></div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-multi-instant-event-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-instant-event-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -829,21 +822,21 @@
 
 </polymer-element><style>
 .analysis-header{font-weight:bold}.analysis-results{font-family:monospace;white-space:pre}.analysis-results *{-webkit-user-select:text!important;cursor:text}.analysis-table{border-collapse:collapse;border-width:0;margin-bottom:25px;width:100%}.analysis-table tr>td:first-child{padding-left:2px}.analysis-table tr>td{padding:2px 4px 2px 4px;vertical-align:text-top;width:150px}.analysis-table td td{padding:0 0 0 0;width:auto}.analysis-table-header{text-align:left}.analysis-table-row{vertical-align:top}.analysis-table-row:nth-child(2n+0){background-color:#e2e2e2}.analysis-table-row-inverted:nth-child(2n+1){background-color:#e2e2e2}.selection-changing-link{color:-webkit-link;cursor:pointer;text-decoration:underline}.analysis-table thead{background-color:#e2e2e2;font-weight:bold}.analysis-table tfoot{font-weight:bold}
-</style><polymer-element name="tv-c-counter-sample-sub-view" extends="tracing-analysis-sub-view">
+</style><polymer-element name="tr-c-a-counter-sample-sub-view" extends="tr-c-a-sub-view">
 
-</polymer-element><polymer-element name="tv-c-single-flow-event-sub-view" extends="tv-c-a-single-event-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-flow-event-sub-view" extends="tr-c-a-single-event-sub-view">
 
-</polymer-element><polymer-element name="tv-c-multi-flow-event-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-flow-event-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
       display: flex;
     }
     </style>
-<tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+<tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-object-instance-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-object-instance-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -877,7 +870,7 @@
 <div id="content"></div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-object-snapshot-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-object-snapshot-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     #args {
@@ -907,27 +900,27 @@
 <content></content>
 </template>
 
-</polymer-element><polymer-element name="tv-c-multi-object-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-object-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
       display: flex;
     }
     </style>
-<tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+<tr-b-ui-table id="content"></tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-sample-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-sample-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
       display: flex;
     }
     </style>
-<tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+<tr-b-ui-table id="content"></tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-multi-sample-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-sample-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -937,11 +930,11 @@
 <div id="content"></div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-interaction-record-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-interaction-record-sub-view" extends="tr-c-a-sub-view">
 
-</polymer-element><polymer-element name="tv-c-multi-interaction-record-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-interaction-record-sub-view" extends="tr-c-a-sub-view">
 
-</polymer-element><polymer-element name="tv-c-a-alert-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-alert-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -953,11 +946,11 @@
       align-self: stretch;
     }
     </style>
-<tracing-analysis-nested-table id="table">
-</tracing-analysis-nested-table>
+<tr-b-ui-table id="table">
+</tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-frame-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-frame-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
@@ -969,36 +962,29 @@
       align-self: stretch;
     }
     </style>
-<tv-c-a-alert-sub-view id="asv">
-</tv-c-a-alert-sub-view>
+<tr-c-a-alert-sub-view id="asv">
+</tr-c-a-alert-sub-view>
 </template>
 
-</polymer-element><polymer-element name="tv-c-multi-frame-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-frame-sub-view" extends="tr-c-a-sub-view">
 
-</polymer-element><polymer-element name="tv-b-color-legend">
+</polymer-element><polymer-element name="tr-b-ui-color-legend">
 <template>
 <style>
     :host {
       display: inline-block;
     }
+
+    #square {
+      font-size: 150%;  /* Make the square bigger. */
+      line-height: 0%;  /* Prevent the square from increasing legend height. */
+    }
     </style>
 <span id="square"></span>
 <span id="label"></span>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-size-span">
-<template>
-<style>
-    :host {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-    }
-    </style>
-<span id="content"></span>
-</template>
-
-</polymer-element><polymer-element name="tv-c-memory-dump-allocator-details-pane">
+</polymer-element><polymer-element name="tr-c-a-memory-dump-allocator-details-pane">
 <template>
 <style>
       :host {
@@ -1035,7 +1021,7 @@
 <div id="contents"></div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-memory-dump-vm-regions-details-pane">
+</polymer-element><polymer-element name="tr-c-a-memory-dump-vm-regions-details-pane">
 <template>
 <style>
       :host {
@@ -1072,7 +1058,7 @@
 <div id="contents"></div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-memory-dump-overview-pane">
+</polymer-element><polymer-element name="tr-c-a-memory-dump-overview-pane">
 <template>
 <style>
       :host {
@@ -1098,11 +1084,11 @@
       }
     </style>
 <div id="label">Overview</div>
-<tracing-analysis-nested-table id="table">
-</tracing-analysis-nested-table>
+<tr-b-ui-table id="table">
+</tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-memory-dump-view">
+</polymer-element><polymer-element name="tr-c-a-memory-dump-view">
 <template>
 <style>
     :host {
@@ -1115,45 +1101,45 @@
       flex: 0 0 auto;
     }
     </style>
-<tv-c-memory-dump-overview-pane id="overview_pane">
-</tv-c-memory-dump-overview-pane>
+<tr-c-a-memory-dump-overview-pane id="overview_pane">
+</tr-c-a-memory-dump-overview-pane>
 <div id="details_pane_container">
 </div>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-process-memory-dump-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-process-memory-dump-sub-view" extends="tr-c-a-sub-view">
 <template>
-<tv-c-memory-dump-view id="memory_dump_view">
-</tv-c-memory-dump-view>
+<tr-c-a-memory-dump-view id="memory_dump_view">
+</tr-c-a-memory-dump-view>
 </template>
 
-</polymer-element><polymer-element name="tv-c-multi-process-memory-dump-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-process-memory-dump-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
       display: flex;
     }
     </style>
-<tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+<tr-b-ui-table id="content"></tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-single-global-memory-dump-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-single-global-memory-dump-sub-view" extends="tr-c-a-sub-view">
 <template>
-<tv-c-memory-dump-view id="memory_dump_view">
-</tv-c-memory-dump-view>
+<tr-c-a-memory-dump-view id="memory_dump_view">
+</tr-c-a-memory-dump-view>
 </template>
 
-</polymer-element><polymer-element name="tv-c-multi-global-memory-dump-sub-view" extends="tracing-analysis-sub-view">
+</polymer-element><polymer-element name="tr-c-a-multi-global-memory-dump-sub-view" extends="tr-c-a-sub-view">
 <template>
 <style>
     :host {
       display: flex;
     }
     </style>
-<tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+<tr-b-ui-table id="content"></tr-b-ui-table>
 </template>
 
-</polymer-element><polymer-element name="tv-c-a-analysis-view">
+</polymer-element><polymer-element name="tr-c-a-analysis-view">
 <template>
 <style>
       :host {
@@ -1355,9 +1341,9 @@
 <div id="prompt" on-keypress="{{ promptKeyPress }}" on-keydown="{{ promptKeyDown }}" on-blur="{{ onConsoleBlur }}">
 </div></div></template>
 
-</polymer-element><polymer-element name="tv-c-side-panel">
+</polymer-element><polymer-element name="tr-c-side-panel">
 
-</polymer-element><polymer-element name="tv-c-side-panel-container" is="HTMLUnknownElement">
+</polymer-element><polymer-element name="tr-c-side-panel-container" is="HTMLUnknownElement">
 <template>
 <style>
     :host {
@@ -1418,7 +1404,7 @@
 </template>
 
 </polymer-element><style>
-x-timeline-view{-webkit-flex-direction:column;cursor:default;display:-webkit-flex;font-family:sans-serif;padding:0}x-timeline-view>.control>.title{font-size:14px;height:22px;padding-left:2px;padding-right:8px;padding-top:2px;flex:1 0 auto}x-timeline-view>.control{background-color:#e6e6e6;background-image:-webkit-gradient(linear,0 0,0 100%,from(#E5E5E5),to(#D1D1D1));flex:0 0 auto;overflow-x:auto}x-timeline-view>.control>.bar{display:flex}x-timeline-view>.control::-webkit-scrollbar{height:0px}x-timeline-view>.control>.bar>#right-controls{margin-left:auto}x-timeline-view>.control>#collapsing-controls{display:-webkit-flex}x-timeline-view>.control .controls{display:-webkit-flex;flex:0 0 auto}x-timeline-view>.control>.bar>span{padding-left:5px;padding-right:10px}x-timeline-view>.control>.bar>.controls button,x-timeline-view>.control>.bar>.controls label,x-timeline-view>.control>.bar>.controls tv-b-dropdown{font-size:14px;margin:1px 2px 1px 2px}x-timeline-view>.control>.bar>.spacer{-webkit-flex:1 1 auto}x-timeline-view>middle-container{-webkit-flex:1 1 auto;-webkit-flex-direction:row;border-bottom:1px solid #8e8e8e;display:-webkit-flex;min-height:0}x-timeline-view>middle-container>track-view-container{-webkit-flex:1 1 auto;display:-webkit-flex;min-height:0;min-width:0}x-timeline-view>middle-container>track-view-container>*{-webkit-flex:1 1 auto}x-timeline-view>middle-container>x-timeline-view-side-panel-container{-webkit-flex:0 0 auto}x-timeline-view>x-drag-handle{-webkit-flex:0 0 auto}x-timeline-view>tv-c-a-analysis-view{-webkit-flex:0 0 auto}x-timeline-view .selection{margin:2px}x-timeline-view .selection ul{margin:0}.button{background-color:#f8f8f8;border:1px solid rgba(0,0,0,0.5);color:rgba(0,0,0,0.8);font-size:14px;height:19px;margin:1px;min-width:23px;text-align:center}x-timeline-view>.control>.bar>.controls tv-b-dropdown{font-size:12px;height:19px;background-color:#f8f8f8}.button:hover{background-color:rgba(255,255,255,1.0);border:1px solid rgba(0,0,0,0.8);box-shadow:0 0 .05em rgba(0,0,0,0.4);color:rgba(0,0,0,1)}.view-info-button{padding-left:4px;padding-right:4px;width:auto}.view-info-button:hover{border:solid 1px}.metadata-dialog-text{font-family:monospace;overflow:auto;white-space:pre}.view-help-text{-webkit-flex:1 1 auto;-webkit-flex-direction:row;display:-webkit-flex;width:700px}.view-help-text .column{width:50%}.view-help-text h2{font-size:1.2em;margin:0;margin-top:5px;text-align:center}.view-help-text h3{margin:0;margin-left:126px;margin-top:10px}.view-help-text .pair{-webkit-flex:1 1 auto;-webkit-flex-direction:row;display:-webkit-flex}.view-help-text .command{font-family:monospace;margin-right:5px;text-align:right;width:150px}.view-help-text .action{font-size:0.9em;text-align:left;width:200px}.view-help-text .mouse-mode-icon{border:1px solid #888;border-radius:3px;box-shadow:inset 0 0 2px rgba(0,0,0,0.3);display:inline-block;height:26px;margin-right:1px;position:relative;top:4px;width:27px;zoom:0.75}.view-help-text .mouse-mode-icon.pan-mode{background-position:-1px -11px}.view-help-text .mouse-mode-icon.select-mode{background-position:-1px -41px}.view-help-text .mouse-mode-icon.zoom-mode{background-position:-1px -71px}.view-help-text .mouse-mode-icon.timing-mode{background-position:-1px -101px}
+x-timeline-view{-webkit-flex-direction:column;cursor:default;display:-webkit-flex;font-family:sans-serif;padding:0}x-timeline-view>.control>.title{font-size:14px;height:22px;padding-left:2px;padding-right:8px;padding-top:2px;flex:1 0 auto}x-timeline-view>.control{background-color:#e6e6e6;background-image:-webkit-gradient(linear,0 0,0 100%,from(#E5E5E5),to(#D1D1D1));flex:0 0 auto;overflow-x:auto}x-timeline-view>.control>.bar{display:flex}x-timeline-view>.control::-webkit-scrollbar{height:0px}x-timeline-view>.control>.bar>#right-controls{margin-left:auto}x-timeline-view>.control>#collapsing-controls{display:-webkit-flex}x-timeline-view>.control .controls{display:-webkit-flex;flex:0 0 auto}x-timeline-view>.control>.bar>span{padding-left:5px;padding-right:10px}x-timeline-view>.control>.bar>.controls button,x-timeline-view>.control>.bar>.controls label,x-timeline-view>.control>.bar>.controls tr-b-ui-dropdown{font-size:14px;margin:1px 2px 1px 2px}x-timeline-view>.control>.bar>.spacer{-webkit-flex:1 1 auto}x-timeline-view>middle-container{-webkit-flex:1 1 auto;-webkit-flex-direction:row;border-bottom:1px solid #8e8e8e;display:-webkit-flex;min-height:0}x-timeline-view>middle-container>track-view-container{-webkit-flex:1 1 auto;display:-webkit-flex;min-height:0;min-width:0}x-timeline-view>middle-container>track-view-container>*{-webkit-flex:1 1 auto}x-timeline-view>middle-container>x-timeline-view-side-panel-container{-webkit-flex:0 0 auto}x-timeline-view>x-drag-handle{-webkit-flex:0 0 auto}x-timeline-view>tr-c-a-analysis-view{-webkit-flex:0 0 auto}x-timeline-view .selection{margin:2px}x-timeline-view .selection ul{margin:0}.button{background-color:#f8f8f8;border:1px solid rgba(0,0,0,0.5);color:rgba(0,0,0,0.8);font-size:14px;height:19px;margin:1px;min-width:23px;text-align:center}x-timeline-view>.control>.bar>.controls tr-b-ui-dropdown{font-size:12px;height:19px;background-color:#f8f8f8}.button:hover{background-color:rgba(255,255,255,1.0);border:1px solid rgba(0,0,0,0.8);box-shadow:0 0 .05em rgba(0,0,0,0.4);color:rgba(0,0,0,1)}.view-info-button{padding-left:4px;padding-right:4px;width:auto}.view-info-button:hover{border:solid 1px}.metadata-dialog-text{font-family:monospace;overflow:auto;white-space:pre}.view-help-text{-webkit-flex:1 1 auto;-webkit-flex-direction:row;display:-webkit-flex;width:700px}.view-help-text .column{width:50%}.view-help-text h2{font-size:1.2em;margin:0;margin-top:5px;text-align:center}.view-help-text h3{margin:0;margin-left:126px;margin-top:10px}.view-help-text .pair{-webkit-flex:1 1 auto;-webkit-flex-direction:row;display:-webkit-flex}.view-help-text .command{font-family:monospace;margin-right:5px;text-align:right;width:150px}.view-help-text .action{font-size:0.9em;text-align:left;width:200px}.view-help-text .mouse-mode-icon{border:1px solid #888;border-radius:3px;box-shadow:inset 0 0 2px rgba(0,0,0,0.3);display:inline-block;height:26px;margin-right:1px;position:relative;top:4px;width:27px;zoom:0.75}.view-help-text .mouse-mode-icon.pan-mode{background-position:-1px -11px}.view-help-text .mouse-mode-icon.select-mode{background-position:-1px -41px}.view-help-text .mouse-mode-icon.zoom-mode{background-position:-1px -71px}.view-help-text .mouse-mode-icon.timing-mode{background-position:-1px -101px}
 </style>
 
 
@@ -1446,10 +1432,10 @@
 </div>
 <middle-container>
 <track-view-container></track-view-container>
-<tv-c-side-panel-container></tv-c-side-panel-container>
+<tr-c-side-panel-container></tr-c-side-panel-container>
 </middle-container>
 <x-drag-handle></x-drag-handle>
-<tv-c-a-analysis-view id="analysis"></tv-c-a-analysis-view>
+<tr-c-a-analysis-view id="analysis"></tr-c-a-analysis-view>
 </template>
 <template id="help-btn-template">
 <div class="button view-help-button">?</div>
@@ -1616,7 +1602,7 @@
 </svg>
 </template><style>
 * /deep/ .line-chart .line{fill:none;stroke-width:1.5px}* /deep/ .line-chart #brushes>rect{fill:rgb(192,192,192)}
-</style><polymer-element name="tv-e-analysis-side-panel-alerts" extends="tv-c-side-panel">
+</style><polymer-element name="tr-e-s-alerts-side-panel" extends="tr-c-side-panel">
 <template>
 <style>
     :host {
@@ -1660,7 +1646,7 @@
 return q(this,d.open(r(this))),t(this,a,e)},HTMLSelectElement.prototype.bind=function(a,c,d){if("selectedindex"===a&&(a="selectedIndex"),"selectedIndex"!==a&&"value"!==a)return HTMLElement.prototype.bind.call(this,a,c,d);if(this.removeAttribute(a),d)return j(this,a,c);var e=c,f=m(this,a,e);return j(this,a,e.open(k(this,a))),b(this,a,f)}}(this),function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a){for(var b;b=a.parentNode;)a=b;return a}function d(a,b){if(b){for(var d,e="#"+b;!d&&(a=c(a),a.protoContent_?d=a.protoContent_.querySelector(e):a.getElementById&&(d=a.getElementById(b)),!d&&a.templateCreator_);)a=a.templateCreator_;return d}}function e(a){return"template"==a.tagName&&"http://www.w3.org/2000/svg"==a.namespaceURI}function f(a){return"TEMPLATE"==a.tagName&&"http://www.w3.org/1999/xhtml"==a.namespaceURI}function g(a){return Boolean(L[a.tagName]&&a.hasAttribute("template"))}function h(a){return void 0===a.isTemplate_&&(a.isTemplate_="TEMPLATE"==a.tagName||g(a)),a.isTemplate_}function i(a,b){var c=a.querySelectorAll(N);h(a)&&b(a),G(c,b)}function j(a){function b(a){HTMLTemplateElement.decorate(a)||j(a.content)}i(a,b)}function k(a,b){Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))})}function l(a){var b=a.ownerDocument;if(!b.defaultView)return b;var c=b.templateContentsOwner_;if(!c){for(c=b.implementation.createHTMLDocument("");c.lastChild;)c.removeChild(c.lastChild);b.templateContentsOwner_=c}return c}function m(a){if(!a.stagingDocument_){var b=a.ownerDocument;if(!b.stagingDocument_){b.stagingDocument_=b.implementation.createHTMLDocument(""),b.stagingDocument_.isStagingDocument=!0;var c=b.stagingDocument_.createElement("base");c.href=document.baseURI,b.stagingDocument_.head.appendChild(c),b.stagingDocument_.stagingDocument_=b.stagingDocument_}a.stagingDocument_=b.stagingDocument_}return a.stagingDocument_}function n(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];K[e.name]&&("template"!==e.name&&b.setAttribute(e.name,e.value),a.removeAttribute(e.name))}return b}function o(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];b.setAttribute(e.name,e.value),a.removeAttribute(e.name)}return a.parentNode.removeChild(a),b}function p(a,b,c){var d=a.content;if(c)return void d.appendChild(b);for(var e;e=b.firstChild;)d.appendChild(e)}function q(a){P?a.__proto__=HTMLTemplateElement.prototype:k(a,HTMLTemplateElement.prototype)}function r(a){a.setModelFn_||(a.setModelFn_=function(){a.setModelFnScheduled_=!1;var b=z(a,a.delegate_&&a.delegate_.prepareBinding);w(a,b,a.model_)}),a.setModelFnScheduled_||(a.setModelFnScheduled_=!0,Observer.runEOM_(a.setModelFn_))}function s(a,b,c,d){if(a&&a.length){for(var e,f=a.length,g=0,h=0,i=0,j=!0;f>h;){var g=a.indexOf("{{",h),k=a.indexOf("[[",h),l=!1,m="}}";if(k>=0&&(0>g||g>k)&&(g=k,l=!0,m="]]"),i=0>g?-1:a.indexOf(m,g+2),0>i){if(!e)return;e.push(a.slice(h));break}e=e||[],e.push(a.slice(h,g));var n=a.slice(g+2,i).trim();e.push(l),j=j&&l;var o=d&&d(n,b,c);e.push(null==o?Path.get(n):null),e.push(o),h=i+2}return h===f&&e.push(""),e.hasOnePath=5===e.length,e.isSimplePath=e.hasOnePath&&""==e[0]&&""==e[4],e.onlyOneTime=j,e.combinator=function(a){for(var b=e[0],c=1;c<e.length;c+=4){var d=e.hasOnePath?a:a[(c-1)/4];void 0!==d&&(b+=d),b+=e[c+3]}return b},e}}function t(a,b,c,d){if(b.hasOnePath){var e=b[3],f=e?e(d,c,!0):b[2].getValueFrom(d);return b.isSimplePath?f:b.combinator(f)}for(var g=[],h=1;h<b.length;h+=4){var e=b[h+2];g[(h-1)/4]=e?e(d,c):b[h+1].getValueFrom(d)}return b.combinator(g)}function u(a,b,c,d){var e=b[3],f=e?e(d,c,!1):new PathObserver(d,b[2]);return b.isSimplePath?f:new ObserverTransform(f,b.combinator)}function v(a,b,c,d){if(b.onlyOneTime)return t(a,b,c,d);if(b.hasOnePath)return u(a,b,c,d);for(var e=new CompoundObserver,f=1;f<b.length;f+=4){var g=b[f],h=b[f+2];if(h){var i=h(d,c,g);g?e.addPath(i):e.addObserver(i)}else{var j=b[f+1];g?e.addPath(j.getValueFrom(d)):e.addPath(d,j)}}return new ObserverTransform(e,b.combinator)}function w(a,b,c,d){for(var e=0;e<b.length;e+=2){var f=b[e],g=b[e+1],h=v(f,g,a,c),i=a.bind(f,h,g.onlyOneTime);i&&d&&d.push(i)}if(a.bindFinished(),b.isTemplate){a.model_=c;var j=a.processBindingDirectives_(b);d&&j&&d.push(j)}}function x(a,b,c){var d=a.getAttribute(b);return s(""==d?"{{}}":d,b,a,c)}function y(a,c){b(a);for(var d=[],e=0;e<a.attributes.length;e++){for(var f=a.attributes[e],g=f.name,i=f.value;"_"===g[0];)g=g.substring(1);if(!h(a)||g!==J&&g!==H&&g!==I){var j=s(i,g,a,c);j&&d.push(g,j)}}return h(a)&&(d.isTemplate=!0,d["if"]=x(a,J,c),d.bind=x(a,H,c),d.repeat=x(a,I,c),!d["if"]||d.bind||d.repeat||(d.bind=s("{{}}",H,a,c))),d}function z(a,b){if(a.nodeType===Node.ELEMENT_NODE)return y(a,b);if(a.nodeType===Node.TEXT_NODE){var c=s(a.data,"textContent",a,b);if(c)return["textContent",c]}return[]}function A(a,b,c,d,e,f,g){for(var h=b.appendChild(c.importNode(a,!1)),i=0,j=a.firstChild;j;j=j.nextSibling)A(j,h,c,d.children[i++],e,f,g);return d.isTemplate&&(HTMLTemplateElement.decorate(h,a),f&&h.setDelegate_(f)),w(h,d,e,g),h}function B(a,b){var c=z(a,b);c.children={};for(var d=0,e=a.firstChild;e;e=e.nextSibling)c.children[d++]=B(e,b);return c}function C(a){var b=a.id_;return b||(b=a.id_=S++),b}function D(a,b){var c=C(a);if(b){var d=b.bindingMaps[c];return d||(d=b.bindingMaps[c]=B(a,b.prepareBinding)||[]),d}var d=a.bindingMap_;return d||(d=a.bindingMap_=B(a,void 0)||[]),d}function E(a){this.closed=!1,this.templateElement_=a,this.instances=[],this.deps=void 0,this.iteratedValue=[],this.presentValue=void 0,this.arrayObserver=void 0}var F,G=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.Map&&"function"==typeof a.Map.prototype.forEach?F=a.Map:(F=function(){this.keys=[],this.values=[]},F.prototype={set:function(a,b){var c=this.keys.indexOf(a);0>c?(this.keys.push(a),this.values.push(b)):this.values[c]=b},get:function(a){var b=this.keys.indexOf(a);if(!(0>b))return this.values[b]},"delete":function(a){var b=this.keys.indexOf(a);return 0>b?!1:(this.keys.splice(b,1),this.values.splice(b,1),!0)},forEach:function(a,b){for(var c=0;c<this.keys.length;c++)a.call(b||this,this.values[c],this.keys[c],this)}});"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)});var H="bind",I="repeat",J="if",K={template:!0,repeat:!0,bind:!0,ref:!0,"if":!0},L={THEAD:!0,TBODY:!0,TFOOT:!0,TH:!0,TR:!0,TD:!0,COLGROUP:!0,COL:!0,CAPTION:!0,OPTION:!0,OPTGROUP:!0},M="undefined"!=typeof HTMLTemplateElement;M&&!function(){var a=document.createElement("template"),b=a.content.ownerDocument,c=b.appendChild(b.createElement("html")),d=c.appendChild(b.createElement("head")),e=b.createElement("base");e.href=document.baseURI,d.appendChild(e)}();var N="template, "+Object.keys(L).map(function(a){return a.toLowerCase()+"[template]"}).join(", ");document.addEventListener("DOMContentLoaded",function(){j(document),Platform.performMicrotaskCheckpoint()},!1),M||(a.HTMLTemplateElement=function(){throw TypeError("Illegal constructor")});var O,P="__proto__"in{};"function"==typeof MutationObserver&&(O=new MutationObserver(function(a){for(var b=0;b<a.length;b++)a[b].target.refChanged_()})),HTMLTemplateElement.decorate=function(a,c){if(a.templateIsDecorated_)return!1;var d=a;d.templateIsDecorated_=!0;var h=f(d)&&M,i=h,k=!h,m=!1;if(h||(g(d)?(b(!c),d=n(a),d.templateIsDecorated_=!0,h=M,m=!0):e(d)&&(d=o(a),d.templateIsDecorated_=!0,h=M)),!h){q(d);var r=l(d);d.content_=r.createDocumentFragment()}return c?d.instanceRef_=c:k?p(d,a,m):i&&j(d.content),!0},HTMLTemplateElement.bootstrap=j;var Q=a.HTMLUnknownElement||HTMLElement,R={get:function(){return this.content_},enumerable:!0,configurable:!0};M||(HTMLTemplateElement.prototype=Object.create(Q.prototype),Object.defineProperty(HTMLTemplateElement.prototype,"content",R)),k(HTMLTemplateElement.prototype,{bind:function(a,b,c){if("ref"!=a)return Element.prototype.bind.call(this,a,b,c);var d=this,e=c?b:b.open(function(a){d.setAttribute("ref",a),d.refChanged_()});return this.setAttribute("ref",e),this.refChanged_(),c?void 0:(this.bindings_?this.bindings_.ref=b:this.bindings_={ref:b},b)},processBindingDirectives_:function(a){return this.iterator_&&this.iterator_.closeDeps(),a["if"]||a.bind||a.repeat?(this.iterator_||(this.iterator_=new E(this)),this.iterator_.updateDependencies(a,this.model_),O&&O.observe(this,{attributes:!0,attributeFilter:["ref"]}),this.iterator_):void(this.iterator_&&(this.iterator_.close(),this.iterator_=void 0))},createInstance:function(a,b,c){b?c=this.newDelegate_(b):c||(c=this.delegate_),this.refContent_||(this.refContent_=this.ref_.content);var d=this.refContent_;if(null===d.firstChild)return T;var e=D(d,c),f=m(this),g=f.createDocumentFragment();g.templateCreator_=this,g.protoContent_=d,g.bindings_=[],g.terminator_=null;for(var h=g.templateInstance_={firstNode:null,lastNode:null,model:a},i=0,j=!1,k=d.firstChild;k;k=k.nextSibling){null===k.nextSibling&&(j=!0);var l=A(k,g,f,e.children[i++],a,c,g.bindings_);l.templateInstance_=h,j&&(g.terminator_=l)}return h.firstNode=g.firstChild,h.lastNode=g.lastChild,g.templateCreator_=void 0,g.protoContent_=void 0,g},get model(){return this.model_},set model(a){this.model_=a,r(this)},get bindingDelegate(){return this.delegate_&&this.delegate_.raw},refChanged_:function(){this.iterator_&&this.refContent_!==this.ref_.content&&(this.refContent_=void 0,this.iterator_.valueChanged(),this.iterator_.updateIteratedValue(this.iterator_.getUpdatedValue()))},clear:function(){this.model_=void 0,this.delegate_=void 0,this.bindings_&&this.bindings_.ref&&this.bindings_.ref.close(),this.refContent_=void 0,this.iterator_&&(this.iterator_.valueChanged(),this.iterator_.close(),this.iterator_=void 0)},setDelegate_:function(a){this.delegate_=a,this.bindingMap_=void 0,this.iterator_&&(this.iterator_.instancePositionChangedFn_=void 0,this.iterator_.instanceModelFn_=void 0)},newDelegate_:function(a){function b(b){var c=a&&a[b];if("function"==typeof c)return function(){return c.apply(a,arguments)}}if(a)return{bindingMaps:{},raw:a,prepareBinding:b("prepareBinding"),prepareInstanceModel:b("prepareInstanceModel"),prepareInstancePositionChanged:b("prepareInstancePositionChanged")}},set bindingDelegate(a){if(this.delegate_)throw Error("Template must be cleared before a new bindingDelegate can be assigned");this.setDelegate_(this.newDelegate_(a))},get ref_(){var a=d(this,this.getAttribute("ref"));if(a||(a=this.instanceRef_),!a)return this;var b=a.ref_;return b?b:a}});var S=1;Object.defineProperty(Node.prototype,"templateInstance",{get:function(){var a=this.templateInstance_;return a?a:this.parentNode?this.parentNode.templateInstance:void 0}});var T=document.createDocumentFragment();T.bindings_=[],T.terminator_=null,E.prototype={closeDeps:function(){var a=this.deps;a&&(a.ifOneTime===!1&&a.ifValue.close(),a.oneTime===!1&&a.value.close())},updateDependencies:function(a,b){this.closeDeps();var c=this.deps={},d=this.templateElement_,e=!0;if(a["if"]){if(c.hasIf=!0,c.ifOneTime=a["if"].onlyOneTime,c.ifValue=v(J,a["if"],d,b),e=c.ifValue,c.ifOneTime&&!e)return void this.valueChanged();c.ifOneTime||(e=e.open(this.updateIfValue,this))}a.repeat?(c.repeat=!0,c.oneTime=a.repeat.onlyOneTime,c.value=v(I,a.repeat,d,b)):(c.repeat=!1,c.oneTime=a.bind.onlyOneTime,c.value=v(H,a.bind,d,b));var f=c.value;return c.oneTime||(f=f.open(this.updateIteratedValue,this)),e?void this.updateValue(f):void this.valueChanged()},getUpdatedValue:function(){var a=this.deps.value;return this.deps.oneTime||(a=a.discardChanges()),a},updateIfValue:function(a){return a?void this.updateValue(this.getUpdatedValue()):void this.valueChanged()},updateIteratedValue:function(a){if(this.deps.hasIf){var b=this.deps.ifValue;if(this.deps.ifOneTime||(b=b.discardChanges()),!b)return void this.valueChanged()}this.updateValue(a)},updateValue:function(a){this.deps.repeat||(a=[a]);var b=this.deps.repeat&&!this.deps.oneTime&&Array.isArray(a);this.valueChanged(a,b)},valueChanged:function(a,b){Array.isArray(a)||(a=[]),a!==this.iteratedValue&&(this.unobserve(),this.presentValue=a,b&&(this.arrayObserver=new ArrayObserver(this.presentValue),this.arrayObserver.open(this.handleSplices,this)),this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,this.iteratedValue)))},getLastInstanceNode:function(a){if(-1==a)return this.templateElement_;var b=this.instances[a],c=b.terminator_;if(!c)return this.getLastInstanceNode(a-1);if(c.nodeType!==Node.ELEMENT_NODE||this.templateElement_===c)return c;var d=c.iterator_;return d?d.getLastTemplateNode():c},getLastTemplateNode:function(){return this.getLastInstanceNode(this.instances.length-1)},insertInstanceAt:function(a,b){var c=this.getLastInstanceNode(a-1),d=this.templateElement_.parentNode;this.instances.splice(a,0,b),d.insertBefore(b,c.nextSibling)},extractInstanceAt:function(a){for(var b=this.getLastInstanceNode(a-1),c=this.getLastInstanceNode(a),d=this.templateElement_.parentNode,e=this.instances.splice(a,1)[0];c!==b;){var f=b.nextSibling;f==c&&(c=b),e.appendChild(d.removeChild(f))}return e},getDelegateFn:function(a){return a=a&&a(this.templateElement_),"function"==typeof a?a:null},handleSplices:function(a){if(!this.closed&&a.length){var b=this.templateElement_;if(!b.parentNode)return void this.close();ArrayObserver.applySplices(this.iteratedValue,this.presentValue,a);var c=b.delegate_;void 0===this.instanceModelFn_&&(this.instanceModelFn_=this.getDelegateFn(c&&c.prepareInstanceModel)),void 0===this.instancePositionChangedFn_&&(this.instancePositionChangedFn_=this.getDelegateFn(c&&c.prepareInstancePositionChanged));for(var d=new F,e=0,f=0;f<a.length;f++){for(var g=a[f],h=g.removed,i=0;i<h.length;i++){var j=h[i],k=this.extractInstanceAt(g.index+e);k!==T&&d.set(j,k)}e-=g.addedCount}for(var f=0;f<a.length;f++)for(var g=a[f],l=g.index;l<g.index+g.addedCount;l++){var j=this.iteratedValue[l],k=d.get(j);k?d["delete"](j):(this.instanceModelFn_&&(j=this.instanceModelFn_(j)),k=void 0===j?T:b.createInstance(j,void 0,c)),this.insertInstanceAt(l,k)}d.forEach(function(a){this.closeInstanceBindings(a)},this),this.instancePositionChangedFn_&&this.reportInstancesMoved(a)}},reportInstanceMoved:function(a){var b=this.instances[a];b!==T&&this.instancePositionChangedFn_(b.templateInstance_,a)},reportInstancesMoved:function(a){for(var b=0,c=0,d=0;d<a.length;d++){var e=a[d];if(0!=c)for(;b<e.index;)this.reportInstanceMoved(b),b++;else b=e.index;for(;b<e.index+e.addedCount;)this.reportInstanceMoved(b),b++;c+=e.addedCount-e.removed.length}if(0!=c)for(var f=this.instances.length;f>b;)this.reportInstanceMoved(b),b++},closeInstanceBindings:function(a){for(var b=a.bindings_,c=0;c<b.length;c++)b[c].close()},unobserve:function(){this.arrayObserver&&(this.arrayObserver.close(),this.arrayObserver=void 0)},close:function(){if(!this.closed){this.unobserve();for(var a=0;a<this.instances.length;a++)this.closeInstanceBindings(this.instances[a]);this.instances.length=0,this.closeDeps(),this.templateElement_.iterator_=void 0,this.closed=!0}}},HTMLTemplateElement.forAllTemplatesFrom_=i}(this),function(a){"use strict";function b(a){return void 0!==m[a]}function c(){h.call(this),this._isInvalid=!0}function d(a){return""==a&&c.call(this),a.toLowerCase()}function e(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,63,96].indexOf(b)?a:encodeURIComponent(a)}function f(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,96].indexOf(b)?a:encodeURIComponent(a)}function g(a,g,h){function i(a){t.push(a)}var j=g||"scheme start",k=0,l="",r=!1,s=!1,t=[];a:for(;(a[k-1]!=o||0==k)&&!this._isInvalid;){var u=a[k];switch(j){case"scheme start":if(!u||!p.test(u)){if(g){i("Invalid scheme.");break a}l="",j="no scheme";continue}l+=u.toLowerCase(),j="scheme";break;case"scheme":if(u&&q.test(u))l+=u.toLowerCase();else{if(":"!=u){if(g){if(o==u)break a;i("Code point not allowed in scheme: "+u);break a}l="",k=0,j="no scheme";continue}if(this._scheme=l,l="",g)break a;b(this._scheme)&&(this._isRelative=!0),j="file"==this._scheme?"relative":this._isRelative&&h&&h._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==u?(query="?",j="query"):"#"==u?(this._fragment="#",j="fragment"):o!=u&&"	"!=u&&"\n"!=u&&"\r"!=u&&(this._schemeData+=e(u));break;case"no scheme":if(h&&b(h._scheme)){j="relative";continue}i("Missing scheme."),c.call(this);break;case"relative or authority":if("/"!=u||"/"!=a[k+1]){i("Expected /, got: "+u),j="relative";continue}j="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=h._scheme),o==u){this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query;break a}if("/"==u||"\\"==u)"\\"==u&&i("\\ is an invalid code point."),j="relative slash";else if("?"==u)this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query="?",j="query";else{if("#"!=u){var v=a[k+1],w=a[k+2];("file"!=this._scheme||!p.test(u)||":"!=v&&"|"!=v||o!=w&&"/"!=w&&"\\"!=w&&"?"!=w&&"#"!=w)&&(this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._path.pop()),j="relative path";continue}this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query,this._fragment="#",j="fragment"}break;case"relative slash":if("/"!=u&&"\\"!=u){"file"!=this._scheme&&(this._host=h._host,this._port=h._port),j="relative path";continue}"\\"==u&&i("\\ is an invalid code point."),j="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=u){i("Expected '/', got: "+u),j="authority ignore slashes";continue}j="authority second slash";break;case"authority second slash":if(j="authority ignore slashes","/"!=u){i("Expected '/', got: "+u);continue}break;case"authority ignore slashes":if("/"!=u&&"\\"!=u){j="authority";continue}i("Expected authority, got: "+u);break;case"authority":if("@"==u){r&&(i("@ already seen."),l+="%40"),r=!0;for(var x=0;x<l.length;x++){var y=l[x];if("	"!=y&&"\n"!=y&&"\r"!=y)if(":"!=y||null!==this._password){var z=e(y);null!==this._password?this._password+=z:this._username+=z}else this._password="";else i("Invalid whitespace in authority.")}l=""}else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){k-=l.length,l="",j="host";continue}l+=u}break;case"file host":if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){2!=l.length||!p.test(l[0])||":"!=l[1]&&"|"!=l[1]?0==l.length?j="relative path start":(this._host=d.call(this,l),l="",j="relative path start"):j="relative path";continue}"	"==u||"\n"==u||"\r"==u?i("Invalid whitespace in file host."):l+=u;break;case"host":case"hostname":if(":"!=u||s){if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){if(this._host=d.call(this,l),l="",j="relative path start",g)break a;continue}"	"!=u&&"\n"!=u&&"\r"!=u?("["==u?s=!0:"]"==u&&(s=!1),l+=u):i("Invalid code point in host/hostname: "+u)}else if(this._host=d.call(this,l),l="",j="port","hostname"==g)break a;break;case"port":if(/[0-9]/.test(u))l+=u;else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u||g){if(""!=l){var A=parseInt(l,10);A!=m[this._scheme]&&(this._port=A+""),l=""}if(g)break a;j="relative path start";continue}"	"==u||"\n"==u||"\r"==u?i("Invalid code point in port: "+u):c.call(this)}break;case"relative path start":if("\\"==u&&i("'\\' not allowed in path."),j="relative path","/"!=u&&"\\"!=u)continue;break;case"relative path":if(o!=u&&"/"!=u&&"\\"!=u&&(g||"?"!=u&&"#"!=u))"	"!=u&&"\n"!=u&&"\r"!=u&&(l+=e(u));else{"\\"==u&&i("\\ not allowed in relative path.");var B;(B=n[l.toLowerCase()])&&(l=B),".."==l?(this._path.pop(),"/"!=u&&"\\"!=u&&this._path.push("")):"."==l&&"/"!=u&&"\\"!=u?this._path.push(""):"."!=l&&("file"==this._scheme&&0==this._path.length&&2==l.length&&p.test(l[0])&&"|"==l[1]&&(l=l[0]+":"),this._path.push(l)),l="","?"==u?(this._query="?",j="query"):"#"==u&&(this._fragment="#",j="fragment")}break;case"query":g||"#"!=u?o!=u&&"	"!=u&&"\n"!=u&&"\r"!=u&&(this._query+=f(u)):(this._fragment="#",j="fragment");break;case"fragment":o!=u&&"	"!=u&&"\n"!=u&&"\r"!=u&&(this._fragment+=u)}k++}}function h(){this._scheme="",this._schemeData="",this._username="",this._password=null,this._host="",this._port="",this._path=[],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}function i(a,b){void 0===b||b instanceof i||(b=new i(String(b))),this._url=a,h.call(this);var c=a.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");g.call(this,c,null,b)}var j=!1;if(!a.forceJURL)try{var k=new URL("b","http://a");k.pathname="c%20d",j="http://a/c%20d"===k.href}catch(l){}if(!j){var m=Object.create(null);m.ftp=21,m.file=0,m.gopher=70,m.http=80,m.https=443,m.ws=80,m.wss=443;var n=Object.create(null);n["%2e"]=".",n[".%2e"]="..",n["%2e."]="..",n["%2e%2e"]="..";var o=void 0,p=/[a-zA-Z]/,q=/[a-zA-Z0-9\+\-\.]/;i.prototype={get href(){if(this._isInvalid)return this._url;var a="";return(""!=this._username||null!=this._password)&&(a=this._username+(null!=this._password?":"+this._password:"")+"@"),this.protocol+(this._isRelative?"//"+a+this.host:"")+this.pathname+this._query+this._fragment},set href(a){h.call(this),g.call(this,a)},get protocol(){return this._scheme+":"},set protocol(a){this._isInvalid||g.call(this,a+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"host")},get hostname(){return this._host},set hostname(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"hostname")},get port(){return this._port},set port(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(a){!this._isInvalid&&this._isRelative&&(this._path=[],g.call(this,a,"relative path start"))},get search(){return this._isInvalid||!this._query||"?"==this._query?"":this._query},set search(a){!this._isInvalid&&this._isRelative&&(this._query="?","?"==a[0]&&(a=a.slice(1)),g.call(this,a,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"==this._fragment?"":this._fragment},set hash(a){this._isInvalid||(this._fragment="#","#"==a[0]&&(a=a.slice(1)),g.call(this,a,"fragment"))},get origin(){var a;if(this._isInvalid||!this._scheme)return"";switch(this._scheme){case"data":case"file":case"javascript":case"mailto":return"null"}return a=this.host,a?this._scheme+"://"+a:""}};var r=a.URL;r&&(i.createObjectURL=function(){return r.createObjectURL.apply(r,arguments)},i.revokeObjectURL=function(a){r.revokeObjectURL(a)}),a.URL=i}}(this),function(a){function b(a){f.textContent=d++,e.push(a)}function c(){for(;e.length;)e.shift()()}var d=0,e=[],f=document.createTextNode("");new(window.MutationObserver||JsMutationObserver)(c).observe(f,{characterData:!0}),a.endOfMicrotask=b,Platform.endOfMicrotask=b}(Polymer),function(a){function b(){g||(g=!0,c(function(){g=!1,d.data&&console.group("flush"),Platform.performMicrotaskCheckpoint(),d.data&&console.groupEnd()}))}var c=a.endOfMicrotask,d=window.WebComponents?WebComponents.flags.log:{},e=document.createElement("style");e.textContent="template {display: none !important;} /* injected by platform.js */";var f=document.querySelector("head");f.insertBefore(e,f.firstChild);var g;if(Observer.hasObjectObserve)b=function(){};else{var h=125;window.addEventListener("WebComponentsReady",function(){b();var c=function(){"hidden"===document.visibilityState?a.flushPoll&&clearInterval(a.flushPoll):a.flushPoll=setInterval(b,h)};"string"==typeof document.visibilityState&&document.addEventListener("visibilitychange",c),c()})}if(window.CustomElements&&!CustomElements.useNative){var i=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=i.call(this,a,b);return CustomElements.upgradeAll(c),c}}a.flush=b,Platform.flush=b}(window.Polymer),function(a){function b(a){var b=new URL(a.ownerDocument.baseURI);return b.search="",b.hash="",b}function c(a,b,c,e){return a.replace(e,function(a,e,f,g){var h=f.replace(/["']/g,"");return h=d(b,h,c),e+"'"+h+"'"+g})}function d(a,b,c){if(b&&"/"===b[0])return b;if(b&&"#"===b[0])return b;var d=new URL(b,a);return c?d.href:e(d.href)}function e(a){var c=b(document.documentElement),d=new URL(a,c);return d.host===c.host&&d.port===c.port&&d.protocol===c.protocol?f(c,d):a}function f(a,b){for(var c=a.pathname,d=b.pathname,e=c.split("/"),f=d.split("/");e.length&&e[0]===f[0];)e.shift(),f.shift();for(var g=0,h=e.length-1;h>g;g++)f.unshift("..");var i=b.href.slice(-1)===m?m:b.hash;return f.join("/")+b.search+i}var g={resolveDom:function(a,c){c=c||b(a),this.resolveAttributes(a,c),this.resolveStyles(a,c);var d=a.querySelectorAll("template");if(d)for(var e,f=0,g=d.length;g>f&&(e=d[f]);f++)e.content&&this.resolveDom(e.content,c)},resolveTemplate:function(a){this.resolveDom(a.content,b(a))},resolveStyles:function(a,b){var c=a.querySelectorAll("style");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveStyle(d,b)},resolveStyle:function(a,c){c=c||b(a),a.textContent=this.resolveCssText(a.textContent,c)},resolveCssText:function(a,b,d){return a=c(a,b,d,h),c(a,b,d,i)},resolveAttributes:function(a,b){a.hasAttributes&&a.hasAttributes()&&this.resolveElementAttributes(a,b);var c=a&&a.querySelectorAll(k);if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveElementAttributes(d,b)},resolveElementAttributes:function(a,e){e=e||b(a),j.forEach(function(b){var f,g=a.attributes[b],i=g&&g.value;i&&i.search(l)<0&&(f="style"===b?c(i,e,!1,h):d(e,i),g.value=f)})}},h=/(url\()([^)]*)(\))/g,i=/(@import[\s]+(?!url\())([^;]*)(;)/g,j=["href","src","action","style","url"],k="["+j.join("],[")+"]",l="{{.*}}",m="#";a.urlResolver=g}(Polymer),function(a){function b(a){this.cache=Object.create(null),this.map=Object.create(null),this.requests=0,this.regex=a}var c=Polymer.endOfMicrotask;b.prototype={extractUrls:function(a,b){for(var c,d,e=[];c=this.regex.exec(a);)d=new URL(c[1],b),e.push({matched:c[0],url:d.href});return e},process:function(a,b,c){var d=this.extractUrls(a,b),e=c.bind(null,this.map);this.fetch(d,e)},fetch:function(a,b){var c=a.length;if(!c)return b();for(var d,e,f,g=function(){0===--c&&b()},h=0;c>h;h++)d=a[h],f=d.url,e=this.cache[f],e||(e=this.xhr(f),e.match=d,this.cache[f]=e),e.wait(g)},handleXhr:function(a){var b=a.match,c=b.url,d=a.response||a.responseText||"";this.map[c]=d,this.fetch(this.extractUrls(d,c),a.resolve)},xhr:function(a){this.requests++;var b=new XMLHttpRequest;return b.open("GET",a,!0),b.send(),b.onerror=b.onload=this.handleXhr.bind(this,b),b.pending=[],b.resolve=function(){for(var a=b.pending,c=0;c<a.length;c++)a[c]();b.pending=null},b.wait=function(a){b.pending?b.pending.push(a):c(a)},b}},a.Loader=b}(Polymer),function(a){function b(){this.loader=new d(this.regex)}var c=a.urlResolver,d=a.Loader;b.prototype={regex:/@import\s+(?:url)?["'\(]*([^'"\)]*)['"\)]*;/g,resolve:function(a,b,c){var d=function(d){c(this.flatten(a,b,d))}.bind(this);this.loader.process(a,b,d)},resolveNode:function(a,b,c){var d=a.textContent,e=function(b){a.textContent=b,c(a)};this.resolve(d,b,e)},flatten:function(a,b,d){for(var e,f,g,h=this.loader.extractUrls(a,b),i=0;i<h.length;i++)e=h[i],f=e.url,g=c.resolveCssText(d[f],f,!0),g=this.flatten(g,b,d),a=a.replace(e.matched,g);return a},loadStyles:function(a,b,c){function d(){f++,f===g&&c&&c()}for(var e,f=0,g=a.length,h=0;g>h&&(e=a[h]);h++)this.resolveNode(e,b,d)}};var e=new b;a.styleResolver=e}(Polymer),function(a){function b(a,b){return a&&b&&Object.getOwnPropertyNames(b).forEach(function(c){var d=Object.getOwnPropertyDescriptor(b,c);d&&(Object.defineProperty(a,c,d),"function"==typeof d.value&&(d.value.nom=c))}),a}function c(a){for(var b=a||{},c=1;c<arguments.length;c++){var e=arguments[c];try{for(var f in e)d(f,e,b)}catch(g){}}return b}function d(a,b,c){var d=e(b,a);Object.defineProperty(c,a,d)}function e(a,b){if(a){var c=Object.getOwnPropertyDescriptor(a,b);return c||e(Object.getPrototypeOf(a),b)}}a.extend=b,a.mixin=c,Platform.mixin=c}(Polymer),function(a){function b(a,b,d){return a?a.stop():a=new c(this),a.go(b,d),a}var c=function(a){this.context=a,this.boundComplete=this.complete.bind(this)};c.prototype={go:function(a,b){this.callback=a;var c;b?(c=setTimeout(this.boundComplete,b),this.handle=function(){clearTimeout(c)}):(c=requestAnimationFrame(this.boundComplete),this.handle=function(){cancelAnimationFrame(c)})},stop:function(){this.handle&&(this.handle(),this.handle=null)},complete:function(){this.handle&&(this.stop(),this.callback.call(this.context))}},a.job=b}(Polymer),function(a){function b(a,b,c){var d="string"==typeof a?document.createElement(a):a.cloneNode(!0);if(d.innerHTML=b,c)for(var e in c)d.setAttribute(e,c[e]);return d}var c={};HTMLElement.register=function(a,b){c[a]=b},HTMLElement.getPrototypeForTag=function(a){var b=a?c[a]:HTMLElement.prototype;return b||Object.getPrototypeOf(document.createElement(a))};var d=Event.prototype.stopPropagation;Event.prototype.stopPropagation=function(){this.cancelBubble=!0,d.apply(this,arguments)};var e=DOMTokenList.prototype.add,f=DOMTokenList.prototype.remove;DOMTokenList.prototype.add=function(){for(var a=0;a<arguments.length;a++)e.call(this,arguments[a])},DOMTokenList.prototype.remove=function(){for(var a=0;a<arguments.length;a++)f.call(this,arguments[a])},DOMTokenList.prototype.toggle=function(a,b){1==arguments.length&&(b=!this.contains(a)),b?this.add(a):this.remove(a)},DOMTokenList.prototype["switch"]=function(a,b){a&&this.remove(a),b&&this.add(b)};var g=function(){return Array.prototype.slice.call(this)},h=window.NamedNodeMap||window.MozNamedAttrMap||{};NodeList.prototype.array=g,h.prototype.array=g,HTMLCollection.prototype.array=g,a.createDOM=b}(Polymer),function(a){function b(a){var e=b.caller,g=e.nom,h=e._super;h||(g||(g=e.nom=c.call(this,e)),g||console.warn("called super() on a method not installed declaratively (has no .nom property)"),h=d(e,g,f(this)));var i=h[g];return i?(i._super||d(i,g,h),i.apply(this,a||[])):void 0}function c(a){for(var b=this.__proto__;b&&b!==HTMLElement.prototype;){for(var c,d=Object.getOwnPropertyNames(b),e=0,f=d.length;f>e&&(c=d[e]);e++){var g=Object.getOwnPropertyDescriptor(b,c);if("function"==typeof g.value&&g.value===a)return c}b=b.__proto__}}function d(a,b,c){var d=e(c,b,a);return d[b]&&(d[b].nom=b),a._super=d}function e(a,b,c){for(;a;){if(a[b]!==c&&a[b])return a;a=f(a)}return Object}function f(a){return a.__proto__}a["super"]=b}(Polymer),function(a){function b(a){return a}function c(a,b){var c=typeof b;return b instanceof Date&&(c="date"),d[c](a,b)}var d={string:b,undefined:b,date:function(a){return new Date(Date.parse(a)||Date.now())},"boolean":function(a){return""===a?!0:"false"===a?!1:!!a},number:function(a){var b=parseFloat(a);return 0===b&&(b=parseInt(a)),isNaN(b)?a:b},object:function(a,b){if(null===b)return a;try{return JSON.parse(a.replace(/'/g,'"'))}catch(c){return a}},"function":function(a,b){return b}};a.deserializeValue=c}(Polymer),function(a){var b=a.extend,c={};c.declaration={},c.instance={},c.publish=function(a,c){for(var d in a)b(c,a[d])},a.api=c}(Polymer),function(a){var b={async:function(a,b,c){Polymer.flush(),b=b&&b.length?b:[b];var d=function(){(this[a]||a).apply(this,b)}.bind(this),e=c?setTimeout(d,c):requestAnimationFrame(d);return c?e:~e},cancelAsync:function(a){0>a?cancelAnimationFrame(~a):clearTimeout(a)},fire:function(a,b,c,d,e){var f=c||this,b=null===b||void 0===b?{}:b,g=new CustomEvent(a,{bubbles:void 0!==d?d:!0,cancelable:void 0!==e?e:!0,detail:b});return f.dispatchEvent(g),g},asyncFire:function(){this.async("fire",arguments)},classFollows:function(a,b,c){b&&b.classList.remove(c),a&&a.classList.add(c)},injectBoundHTML:function(a,b){var c=document.createElement("template");c.innerHTML=a;var d=this.instanceTemplate(c);return b&&(b.textContent="",b.appendChild(d)),d}},c=function(){},d={};b.asyncMethod=b.async,a.api.instance.utils=b,a.nop=c,a.nob=d}(Polymer),function(a){var b=window.WebComponents?WebComponents.flags.log:{},c="on-",d={EVENT_PREFIX:c,addHostListeners:function(){var a=this.eventDelegates;
 b.events&&Object.keys(a).length>0&&console.log("[%s] addHostListeners:",this.localName,a);for(var c in a){var d=a[c];PolymerGestures.addEventListener(this,c,this.element.getEventHandler(this,this,d))}},dispatchMethod:function(a,c,d){if(a){b.events&&console.group("[%s] dispatch [%s]",a.localName,c);var e="function"==typeof c?c:a[c];e&&e[d?"apply":"call"](a,d),b.events&&console.groupEnd(),Polymer.flush()}}};a.api.instance.events=d,a.addEventListener=function(a,b,c,d){PolymerGestures.addEventListener(wrap(a),b,c,d)},a.removeEventListener=function(a,b,c,d){PolymerGestures.removeEventListener(wrap(a),b,c,d)}}(Polymer),function(a){var b={copyInstanceAttributes:function(){var a=this._instanceAttributes;for(var b in a)this.hasAttribute(b)||this.setAttribute(b,a[b])},takeAttributes:function(){if(this._publishLC)for(var a,b=0,c=this.attributes,d=c.length;(a=c[b])&&d>b;b++)this.attributeToProperty(a.name,a.value)},attributeToProperty:function(b,c){var b=this.propertyForAttribute(b);if(b){if(c&&c.search(a.bindPattern)>=0)return;var d=this[b],c=this.deserializeValue(c,d);c!==d&&(this[b]=c)}},propertyForAttribute:function(a){var b=this._publishLC&&this._publishLC[a];return b},deserializeValue:function(b,c){return a.deserializeValue(b,c)},serializeValue:function(a,b){return"boolean"===b?a?"":void 0:"object"!==b&&"function"!==b&&void 0!==a?a:void 0},reflectPropertyToAttribute:function(a){var b=typeof this[a],c=this.serializeValue(this[a],b);void 0!==c?this.setAttribute(a,c):"boolean"===b&&this.removeAttribute(a)}};a.api.instance.attributes=b}(Polymer),function(a){function b(a,b){return a===b?0!==a||1/a===1/b:f(a)&&f(b)?!0:a!==a&&b!==b}function c(a,b){return void 0===b&&null===a?b:null===b||void 0===b?a:b}var d=window.WebComponents?WebComponents.flags.log:{},e={object:void 0,type:"update",name:void 0,oldValue:void 0},f=Number.isNaN||function(a){return"number"==typeof a&&isNaN(a)},g={createPropertyObserver:function(){var a=this._observeNames;if(a&&a.length){var b=this._propertyObserver=new CompoundObserver(!0);this.registerObserver(b);for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)b.addPath(this,c),this.observeArrayValue(c,this[c],null)}},openPropertyObserver:function(){this._propertyObserver&&this._propertyObserver.open(this.notifyPropertyChanges,this)},notifyPropertyChanges:function(a,b,c){var d,e,f={};for(var g in b)if(d=c[2*g+1],e=this.observe[d]){var h=b[g],i=a[g];this.observeArrayValue(d,i,h),f[e]||(void 0!==h&&null!==h||void 0!==i&&null!==i)&&(f[e]=!0,this.invokeMethod(e,[h,i,arguments]))}},invokeMethod:function(a,b){var c=this[a]||a;"function"==typeof c&&c.apply(this,b)},deliverChanges:function(){this._propertyObserver&&this._propertyObserver.deliver()},observeArrayValue:function(a,b,c){var e=this.observe[a];if(e&&(Array.isArray(c)&&(d.observe&&console.log("[%s] observeArrayValue: unregister observer [%s]",this.localName,a),this.closeNamedObserver(a+"__array")),Array.isArray(b))){d.observe&&console.log("[%s] observeArrayValue: register observer [%s]",this.localName,a,b);var f=new ArrayObserver(b);f.open(function(a){this.invokeMethod(e,[a])},this),this.registerNamedObserver(a+"__array",f)}},emitPropertyChangeRecord:function(a,c,d){if(!b(c,d)&&(this._propertyChanged(a,c,d),Observer.hasObjectObserve)){var f=this._objectNotifier;f||(f=this._objectNotifier=Object.getNotifier(this)),e.object=this,e.name=a,e.oldValue=d,f.notify(e)}},_propertyChanged:function(a){this.reflect[a]&&this.reflectPropertyToAttribute(a)},bindProperty:function(a,b,d){if(d)return void(this[a]=b);var e=this.element.prototype.computed;if(e&&e[a]){var f=a+"ComputedBoundObservable_";return void(this[f]=b)}return this.bindToAccessor(a,b,c)},bindToAccessor:function(a,c,d){function e(b,c){j[f]=b;var d=j[h];d&&"function"==typeof d.setValue&&d.setValue(b),j.emitPropertyChangeRecord(a,b,c)}var f=a+"_",g=a+"Observable_",h=a+"ComputedBoundObservable_";this[g]=c;var i=this[f],j=this,k=c.open(e);if(d&&!b(i,k)){var l=d(i,k);b(k,l)||(k=l,c.setValue&&c.setValue(k))}e(k,i);var m={close:function(){c.close(),j[g]=void 0,j[h]=void 0}};return this.registerObserver(m),m},createComputedProperties:function(){if(this._computedNames)for(var a=0;a<this._computedNames.length;a++){var b=this._computedNames[a],c=this.computed[b];try{var d=PolymerExpressions.getExpression(c),e=d.getBinding(this,this.element.syntax);this.bindToAccessor(b,e)}catch(f){console.error("Failed to create computed property",f)}}},registerObserver:function(a){return this._observers?void this._observers.push(a):void(this._observers=[a])},closeObservers:function(){if(this._observers){for(var a=this._observers,b=0;b<a.length;b++){var c=a[b];c&&"function"==typeof c.close&&c.close()}this._observers=[]}},registerNamedObserver:function(a,b){var c=this._namedObservers||(this._namedObservers={});c[a]=b},closeNamedObserver:function(a){var b=this._namedObservers;return b&&b[a]?(b[a].close(),b[a]=null,!0):void 0},closeNamedObservers:function(){if(this._namedObservers){for(var a in this._namedObservers)this.closeNamedObserver(a);this._namedObservers={}}}};a.api.instance.properties=g}(Polymer),function(a){var b=window.WebComponents?WebComponents.flags.log:{},c={instanceTemplate:function(a){HTMLTemplateElement.decorate(a);for(var b=this.syntax||!a.bindingDelegate&&this.element.syntax,c=a.createInstance(this,b),d=c.bindings_,e=0;e<d.length;e++)this.registerObserver(d[e]);return c},bind:function(a,b,c){var d=this.propertyForAttribute(a);if(d){var e=this.bindProperty(d,b,c);return Platform.enableBindingsReflection&&e&&(e.path=b.path_,this._recordBinding(d,e)),this.reflect[d]&&this.reflectPropertyToAttribute(d),e}return this.mixinSuper(arguments)},_recordBinding:function(a,b){this.bindings_=this.bindings_||{},this.bindings_[a]=b},bindFinished:function(){this.makeElementReady()},asyncUnbindAll:function(){this._unbound||(b.unbind&&console.log("[%s] asyncUnbindAll",this.localName),this._unbindAllJob=this.job(this._unbindAllJob,this.unbindAll,0))},unbindAll:function(){this._unbound||(this.closeObservers(),this.closeNamedObservers(),this._unbound=!0)},cancelUnbindAll:function(){return this._unbound?void(b.unbind&&console.warn("[%s] already unbound, cannot cancel unbindAll",this.localName)):(b.unbind&&console.log("[%s] cancelUnbindAll",this.localName),void(this._unbindAllJob&&(this._unbindAllJob=this._unbindAllJob.stop())))}},d=/\{\{([^{}]*)}}/;a.bindPattern=d,a.api.instance.mdv=c}(Polymer),function(a){function b(a){return a.hasOwnProperty("PolymerBase")}function c(){}var d={PolymerBase:!0,job:function(a,b,c){if("string"!=typeof a)return Polymer.job.call(this,a,b,c);var d="___"+a;this[d]=Polymer.job.call(this,this[d],b,c)},"super":Polymer["super"],created:function(){},ready:function(){},createdCallback:function(){this.templateInstance&&this.templateInstance.model&&console.warn("Attributes on "+this.localName+" were data bound prior to Polymer upgrading the element. This may result in incorrect binding types."),this.created(),this.prepareElement(),this.ownerDocument.isStagingDocument||this.makeElementReady()},prepareElement:function(){return this._elementPrepared?void console.warn("Element already prepared",this.localName):(this._elementPrepared=!0,this.shadowRoots={},this.createPropertyObserver(),this.openPropertyObserver(),this.copyInstanceAttributes(),this.takeAttributes(),void this.addHostListeners())},makeElementReady:function(){this._readied||(this._readied=!0,this.createComputedProperties(),this.parseDeclarations(this.__proto__),this.removeAttribute("unresolved"),this.ready())},attributeChangedCallback:function(a){"class"!==a&&"style"!==a&&this.attributeToProperty(a,this.getAttribute(a)),this.attributeChanged&&this.attributeChanged.apply(this,arguments)},attachedCallback:function(){this.cancelUnbindAll(),this.attached&&this.attached(),this.hasBeenAttached||(this.hasBeenAttached=!0,this.domReady&&this.async("domReady"))},detachedCallback:function(){this.preventDispose||this.asyncUnbindAll(),this.detached&&this.detached(),this.leftView&&this.leftView()},parseDeclarations:function(a){a&&a.element&&(this.parseDeclarations(a.__proto__),a.parseDeclaration.call(this,a.element))},parseDeclaration:function(a){var b=this.fetchTemplate(a);if(b){var c=this.shadowFromTemplate(b);this.shadowRoots[a.name]=c}},fetchTemplate:function(a){return a.querySelector("template")},shadowFromTemplate:function(a){if(a){var b=this.createShadowRoot(),c=this.instanceTemplate(a);return b.appendChild(c),this.shadowRootReady(b,a),b}},lightFromTemplate:function(a,b){if(a){this.eventController=this;var c=this.instanceTemplate(a);return b?this.insertBefore(c,b):this.appendChild(c),this.shadowRootReady(this),c}},shadowRootReady:function(a){this.marshalNodeReferences(a)},marshalNodeReferences:function(a){var b=this.$=this.$||{};if(a)for(var c,d=a.querySelectorAll("[id]"),e=0,f=d.length;f>e&&(c=d[e]);e++)b[c.id]=c},onMutation:function(a,b){var c=new MutationObserver(function(a){b.call(this,c,a),c.disconnect()}.bind(this));c.observe(a,{childList:!0,subtree:!0})}};c.prototype=d,d.constructor=c,a.Base=c,a.isBase=b,a.api.instance.base=d}(Polymer),function(a){function b(a){return a.__proto__}function c(a,b){var c="",d=!1;b&&(c=b.localName,d=b.hasAttribute("is"));var e=WebComponents.ShadowCSS.makeScopeSelector(c,d);return WebComponents.ShadowCSS.shimCssText(a,e)}var d=(window.WebComponents?WebComponents.flags.log:{},window.ShadowDOMPolyfill),e="element",f="controller",g={STYLE_SCOPE_ATTRIBUTE:e,installControllerStyles:function(){var a=this.findStyleScope();if(a&&!this.scopeHasNamedStyle(a,this.localName)){for(var c=b(this),d="";c&&c.element;)d+=c.element.cssTextForScope(f),c=b(c);d&&this.installScopeCssText(d,a)}},installScopeStyle:function(a,b,c){var c=c||this.findStyleScope(),b=b||"";if(c&&!this.scopeHasNamedStyle(c,this.localName+b)){var d="";if(a instanceof Array)for(var e,f=0,g=a.length;g>f&&(e=a[f]);f++)d+=e.textContent+"\n\n";else d=a.textContent;this.installScopeCssText(d,c,b)}},installScopeCssText:function(a,b,e){if(b=b||this.findStyleScope(),e=e||"",b){d&&(a=c(a,b.host));var g=this.element.cssTextToScopeStyle(a,f);Polymer.applyStyleToScope(g,b),this.styleCacheForScope(b)[this.localName+e]=!0}},findStyleScope:function(a){for(var b=a||this;b.parentNode;)b=b.parentNode;return b},scopeHasNamedStyle:function(a,b){var c=this.styleCacheForScope(a);return c[b]},styleCacheForScope:function(a){if(d){var b=a.host?a.host.localName:a.localName;return h[b]||(h[b]={})}return a._scopeStyles=a._scopeStyles||{}}},h={};a.api.instance.styles=g}(Polymer),function(a){function b(a,b){if("string"!=typeof a){var c=b||document._currentScript;if(b=a,a=c&&c.parentNode&&c.parentNode.getAttribute?c.parentNode.getAttribute("name"):"",!a)throw"Element name could not be inferred."}if(f(a))throw"Already registered (Polymer) prototype for element "+a;e(a,b),d(a)}function c(a,b){i[a]=b}function d(a){i[a]&&(i[a].registerWhenReady(),delete i[a])}function e(a,b){return j[a]=b||{}}function f(a){return j[a]}function g(a,b){if("string"!=typeof b)return!1;var c=HTMLElement.getPrototypeForTag(b),d=c&&c.constructor;return d?CustomElements["instanceof"]?CustomElements["instanceof"](a,d):a instanceof d:!1}var h=a.extend,i=(a.api,{}),j={};a.getRegisteredPrototype=f,a.waitingForPrototype=c,a.instanceOfType=g,window.Polymer=b,h(Polymer,a),WebComponents.consumeDeclarations&&WebComponents.consumeDeclarations(function(a){if(a)for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)b.apply(null,c)})}(Polymer),function(a){var b={resolveElementPaths:function(a){Polymer.urlResolver.resolveDom(a)},addResolvePathApi:function(){var a=this.getAttribute("assetpath")||"",b=new URL(a,this.ownerDocument.baseURI);this.prototype.resolvePath=function(a,c){var d=new URL(a,c||b);return d.href}}};a.api.declaration.path=b}(Polymer),function(a){function b(a,b){var c=new URL(a.getAttribute("href"),b).href;return"@import '"+c+"';"}function c(a,b){if(a){b===document&&(b=document.head),i&&(b=document.head);var c=d(a.textContent),e=a.getAttribute(h);e&&c.setAttribute(h,e);var f=b.firstElementChild;if(b===document.head){var g="style["+h+"]",j=document.head.querySelectorAll(g);j.length&&(f=j[j.length-1].nextElementSibling)}b.insertBefore(c,f)}}function d(a,b){b=b||document,b=b.createElement?b:b.ownerDocument;var c=b.createElement("style");return c.textContent=a,c}function e(a){return a&&a.__resource||""}function f(a,b){return q?q.call(a,b):void 0}var g=(window.WebComponents?WebComponents.flags.log:{},a.api.instance.styles),h=g.STYLE_SCOPE_ATTRIBUTE,i=window.ShadowDOMPolyfill,j="style",k="@import",l="link[rel=stylesheet]",m="global",n="polymer-scope",o={loadStyles:function(a){var b=this.fetchTemplate(),c=b&&this.templateContent();if(c){this.convertSheetsToStyles(c);var d=this.findLoadableStyles(c);if(d.length){var e=b.ownerDocument.baseURI;return Polymer.styleResolver.loadStyles(d,e,a)}}a&&a()},convertSheetsToStyles:function(a){for(var c,e,f=a.querySelectorAll(l),g=0,h=f.length;h>g&&(c=f[g]);g++)e=d(b(c,this.ownerDocument.baseURI),this.ownerDocument),this.copySheetAttributes(e,c),c.parentNode.replaceChild(e,c)},copySheetAttributes:function(a,b){for(var c,d=0,e=b.attributes,f=e.length;(c=e[d])&&f>d;d++)"rel"!==c.name&&"href"!==c.name&&a.setAttribute(c.name,c.value)},findLoadableStyles:function(a){var b=[];if(a)for(var c,d=a.querySelectorAll(j),e=0,f=d.length;f>e&&(c=d[e]);e++)c.textContent.match(k)&&b.push(c);return b},installSheets:function(){this.cacheSheets(),this.cacheStyles(),this.installLocalSheets(),this.installGlobalStyles()},cacheSheets:function(){this.sheets=this.findNodes(l),this.sheets.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},cacheStyles:function(){this.styles=this.findNodes(j+"["+n+"]"),this.styles.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},installLocalSheets:function(){var a=this.sheets.filter(function(a){return!a.hasAttribute(n)}),b=this.templateContent();if(b){var c="";if(a.forEach(function(a){c+=e(a)+"\n"}),c){var f=d(c,this.ownerDocument);b.insertBefore(f,b.firstChild)}}},findNodes:function(a,b){var c=this.querySelectorAll(a).array(),d=this.templateContent();if(d){var e=d.querySelectorAll(a).array();c=c.concat(e)}return b?c.filter(b):c},installGlobalStyles:function(){var a=this.styleForScope(m);c(a,document.head)},cssTextForScope:function(a){var b="",c="["+n+"="+a+"]",d=function(a){return f(a,c)},g=this.sheets.filter(d);g.forEach(function(a){b+=e(a)+"\n\n"});var h=this.styles.filter(d);return h.forEach(function(a){b+=a.textContent+"\n\n"}),b},styleForScope:function(a){var b=this.cssTextForScope(a);return this.cssTextToScopeStyle(b,a)},cssTextToScopeStyle:function(a,b){if(a){var c=d(a);return c.setAttribute(h,this.getAttribute("name")+"-"+b),c}}},p=HTMLElement.prototype,q=p.matches||p.matchesSelector||p.webkitMatchesSelector||p.mozMatchesSelector;a.api.declaration.styles=o,a.applyStyleToScope=c}(Polymer),function(a){var b=(window.WebComponents?WebComponents.flags.log:{},a.api.instance.events),c=b.EVENT_PREFIX,d={};["webkitAnimationStart","webkitAnimationEnd","webkitTransitionEnd","DOMFocusOut","DOMFocusIn","DOMMouseScroll"].forEach(function(a){d[a.toLowerCase()]=a});var e={parseHostEvents:function(){var a=this.prototype.eventDelegates;this.addAttributeDelegates(a)},addAttributeDelegates:function(a){for(var b,c=0;b=this.attributes[c];c++)this.hasEventPrefix(b.name)&&(a[this.removeEventPrefix(b.name)]=b.value.replace("{{","").replace("}}","").trim())},hasEventPrefix:function(a){return a&&"o"===a[0]&&"n"===a[1]&&"-"===a[2]},removeEventPrefix:function(a){return a.slice(f)},findController:function(a){for(;a.parentNode;){if(a.eventController)return a.eventController;a=a.parentNode}return a.host},getEventHandler:function(a,b,c){var d=this;return function(e){a&&a.PolymerBase||(a=d.findController(b));var f=[e,e.detail,e.currentTarget];a.dispatchMethod(a,c,f)}},prepareEventBinding:function(a,b){if(this.hasEventPrefix(b)){var c=this.removeEventPrefix(b);c=d[c]||c;var e=this;return function(b,d,f){function g(){return"{{ "+a+" }}"}var h=e.getEventHandler(void 0,d,a);return PolymerGestures.addEventListener(d,c,h),f?void 0:{open:g,discardChanges:g,close:function(){PolymerGestures.removeEventListener(d,c,h)}}}}}},f=c.length;a.api.declaration.events=e}(Polymer),function(a){var b=["attribute"],c={inferObservers:function(a){var b,c=a.observe;for(var d in a)"Changed"===d.slice(-7)&&(b=d.slice(0,-7),this.canObserveProperty(b)&&(c||(c=a.observe={}),c[b]=c[b]||d))},canObserveProperty:function(a){return b.indexOf(a)<0},explodeObservers:function(a){var b=a.observe;if(b){var c={};for(var d in b)for(var e,f=d.split(" "),g=0;e=f[g];g++)c[e]=b[d];a.observe=c}},optimizePropertyMaps:function(a){if(a.observe){var b=a._observeNames=[];for(var c in a.observe)for(var d,e=c.split(" "),f=0;d=e[f];f++)b.push(d)}if(a.publish){var b=a._publishNames=[];for(var c in a.publish)b.push(c)}if(a.computed){var b=a._computedNames=[];for(var c in a.computed)b.push(c)}},publishProperties:function(a,b){var c=a.publish;c&&(this.requireProperties(c,a,b),this.filterInvalidAccessorNames(c),a._publishLC=this.lowerCaseMap(c));var d=a.computed;d&&this.filterInvalidAccessorNames(d)},filterInvalidAccessorNames:function(a){for(var b in a)this.propertyNameBlacklist[b]&&(console.warn('Cannot define property "'+b+'" for element "'+this.name+'" because it has the same name as an HTMLElement property, and not all browsers support overriding that. Consider giving it a different name.'),delete a[b])},requireProperties:function(a,b){b.reflect=b.reflect||{};for(var c in a){var d=a[c];d&&void 0!==d.reflect&&(b.reflect[c]=Boolean(d.reflect),d=d.value),void 0!==d&&(b[c]=d)}},lowerCaseMap:function(a){var b={};for(var c in a)b[c.toLowerCase()]=c;return b},createPropertyAccessor:function(a,b){var c=this.prototype,d=a+"_",e=a+"Observable_";c[d]=c[a],Object.defineProperty(c,a,{get:function(){var a=this[e];return a&&a.deliver(),this[d]},set:function(c){if(b)return this[d];var f=this[e];if(f)return void f.setValue(c);var g=this[d];return this[d]=c,this.emitPropertyChangeRecord(a,c,g),c},configurable:!0})},createPropertyAccessors:function(a){var b=a._computedNames;if(b&&b.length)for(var c,d=0,e=b.length;e>d&&(c=b[d]);d++)this.createPropertyAccessor(c,!0);var b=a._publishNames;if(b&&b.length)for(var c,d=0,e=b.length;e>d&&(c=b[d]);d++)a.computed&&a.computed[c]||this.createPropertyAccessor(c)},propertyNameBlacklist:{children:1,"class":1,id:1,hidden:1,style:1,title:1}};a.api.declaration.properties=c}(Polymer),function(a){var b="attributes",c=/\s|,/,d={inheritAttributesObjects:function(a){this.inheritObject(a,"publishLC"),this.inheritObject(a,"_instanceAttributes")},publishAttributes:function(a){var d=this.getAttribute(b);if(d)for(var e,f=a.publish||(a.publish={}),g=d.split(c),h=0,i=g.length;i>h;h++)e=g[h].trim(),e&&void 0===f[e]&&(f[e]=void 0)},accumulateInstanceAttributes:function(){for(var a,b=this.prototype._instanceAttributes,c=this.attributes,d=0,e=c.length;e>d&&(a=c[d]);d++)this.isInstanceAttribute(a.name)&&(b[a.name]=a.value)},isInstanceAttribute:function(a){return!this.blackList[a]&&"on-"!==a.slice(0,3)},blackList:{name:1,"extends":1,constructor:1,noscript:1,assetpath:1,"cache-csstext":1}};d.blackList[b]=1,a.api.declaration.attributes=d}(Polymer),function(a){var b=a.api.declaration.events,c=new PolymerExpressions,d=c.prepareBinding;c.prepareBinding=function(a,e,f){return b.prepareEventBinding(a,e,f)||d.call(c,a,e,f)};var e={syntax:c,fetchTemplate:function(){return this.querySelector("template")},templateContent:function(){var a=this.fetchTemplate();return a&&a.content},installBindingDelegate:function(a){a&&(a.bindingDelegate=this.syntax)}};a.api.declaration.mdv=e}(Polymer),function(a){function b(a){if(!Object.__proto__){var b=Object.getPrototypeOf(a);a.__proto__=b,d(b)&&(b.__proto__=Object.getPrototypeOf(b))}}var c=a.api,d=a.isBase,e=a.extend,f=window.ShadowDOMPolyfill,g={register:function(a,b){this.buildPrototype(a,b),this.registerPrototype(a,b),this.publishConstructor()},buildPrototype:function(b,c){var d=a.getRegisteredPrototype(b),e=this.generateBasePrototype(c);this.desugarBeforeChaining(d,e),this.prototype=this.chainPrototypes(d,e),this.desugarAfterChaining(b,c)},desugarBeforeChaining:function(a,b){a.element=this,this.publishAttributes(a,b),this.publishProperties(a,b),this.inferObservers(a),this.explodeObservers(a)},chainPrototypes:function(a,c){this.inheritMetaData(a,c);var d=this.chainObject(a,c);return b(d),d},inheritMetaData:function(a,b){this.inheritObject("observe",a,b),this.inheritObject("publish",a,b),this.inheritObject("reflect",a,b),this.inheritObject("_publishLC",a,b),this.inheritObject("_instanceAttributes",a,b),this.inheritObject("eventDelegates",a,b)},desugarAfterChaining:function(a,b){this.optimizePropertyMaps(this.prototype),this.createPropertyAccessors(this.prototype),this.installBindingDelegate(this.fetchTemplate()),this.installSheets(),this.resolveElementPaths(this),this.accumulateInstanceAttributes(),this.parseHostEvents(),this.addResolvePathApi(),f&&WebComponents.ShadowCSS.shimStyling(this.templateContent(),a,b),this.prototype.registerCallback&&this.prototype.registerCallback(this)},publishConstructor:function(){var a=this.getAttribute("constructor");a&&(window[a]=this.ctor)},generateBasePrototype:function(a){var b=this.findBasePrototype(a);if(!b){var b=HTMLElement.getPrototypeForTag(a);b=this.ensureBaseApi(b),h[a]=b}return b},findBasePrototype:function(a){return h[a]},ensureBaseApi:function(a){if(a.PolymerBase)return a;var b=Object.create(a);return c.publish(c.instance,b),this.mixinMethod(b,a,c.instance.mdv,"bind"),b},mixinMethod:function(a,b,c,d){var e=function(a){return b[d].apply(this,a)};a[d]=function(){return this.mixinSuper=e,c[d].apply(this,arguments)}},inheritObject:function(a,b,c){var d=b[a]||{};b[a]=this.chainObject(d,c[a])},registerPrototype:function(a,b){var c={prototype:this.prototype},d=this.findTypeExtension(b);d&&(c["extends"]=d),HTMLElement.register(a,this.prototype),this.ctor=document.registerElement(a,c)},findTypeExtension:function(a){if(a&&a.indexOf("-")<0)return a;var b=this.findBasePrototype(a);return b.element?this.findTypeExtension(b.element["extends"]):void 0}},h={};g.chainObject=Object.__proto__?function(a,b){return a&&b&&a!==b&&(a.__proto__=b),a}:function(a,b){if(a&&b&&a!==b){var c=Object.create(b);a=e(c,a)}return a},c.declaration.prototype=g}(Polymer),function(a){function b(a){return document.contains(a)?j:i}function c(){return i.length?i[0]:j[0]}function d(a){f.waitToReady=!0,Polymer.endOfMicrotask(function(){HTMLImports.whenReady(function(){f.addReadyCallback(a),f.waitToReady=!1,f.check()})})}function e(a){if(void 0===a)return void f.ready();var b=setTimeout(function(){f.ready()},a);Polymer.whenReady(function(){clearTimeout(b)})}var f={wait:function(a){a.__queue||(a.__queue={},g.push(a))},enqueue:function(a,c,d){var e=a.__queue&&!a.__queue.check;return e&&(b(a).push(a),a.__queue.check=c,a.__queue.go=d),0!==this.indexOf(a)},indexOf:function(a){var c=b(a).indexOf(a);return c>=0&&document.contains(a)&&(c+=HTMLImports.useNative||HTMLImports.ready?i.length:1e9),c},go:function(a){var b=this.remove(a);b&&(a.__queue.flushable=!0,this.addToFlushQueue(b),this.check())},remove:function(a){var c=this.indexOf(a);if(0===c)return b(a).shift()},check:function(){var a=this.nextElement();return a&&a.__queue.check.call(a),this.canReady()?(this.ready(),!0):void 0},nextElement:function(){return c()},canReady:function(){return!this.waitToReady&&this.isEmpty()},isEmpty:function(){for(var a,b=0,c=g.length;c>b&&(a=g[b]);b++)if(a.__queue&&!a.__queue.flushable)return;return!0},addToFlushQueue:function(a){h.push(a)},flush:function(){if(!this.flushing){this.flushing=!0;for(var a;h.length;)a=h.shift(),a.__queue.go.call(a),a.__queue=null;this.flushing=!1}},ready:function(){var a=CustomElements.ready;CustomElements.ready=!1,this.flush(),CustomElements.useNative||CustomElements.upgradeDocumentTree(document),CustomElements.ready=a,Polymer.flush(),requestAnimationFrame(this.flushReadyCallbacks)},addReadyCallback:function(a){a&&k.push(a)},flushReadyCallbacks:function(){if(k)for(var a;k.length;)(a=k.shift())()},waitingFor:function(){for(var a,b=[],c=0,d=g.length;d>c&&(a=g[c]);c++)a.__queue&&!a.__queue.flushable&&b.push(a);return b},waitToReady:!0},g=[],h=[],i=[],j=[],k=[];a.elements=g,a.waitingFor=f.waitingFor.bind(f),a.forceReady=e,a.queue=f,a.whenReady=a.whenPolymerReady=d}(Polymer),function(a){function b(a){return Boolean(HTMLElement.getPrototypeForTag(a))}function c(a){return a&&a.indexOf("-")>=0}var d=a.extend,e=a.api,f=a.queue,g=a.whenReady,h=a.getRegisteredPrototype,i=a.waitingForPrototype,j=d(Object.create(HTMLElement.prototype),{createdCallback:function(){this.getAttribute("name")&&this.init()},init:function(){this.name=this.getAttribute("name"),this["extends"]=this.getAttribute("extends"),f.wait(this),this.loadResources(),this.registerWhenReady()},registerWhenReady:function(){this.registered||this.waitingForPrototype(this.name)||this.waitingForQueue()||this.waitingForResources()||f.go(this)},_register:function(){c(this["extends"])&&!b(this["extends"])&&console.warn("%s is attempting to extend %s, an unregistered element or one that was not registered with Polymer.",this.name,this["extends"]),this.register(this.name,this["extends"]),this.registered=!0},waitingForPrototype:function(a){return h(a)?void 0:(i(a,this),this.handleNoScript(a),!0)},handleNoScript:function(a){this.hasAttribute("noscript")&&!this.noscript&&(this.noscript=!0,Polymer(a))},waitingForResources:function(){return this._needsResources},waitingForQueue:function(){return f.enqueue(this,this.registerWhenReady,this._register)},loadResources:function(){this._needsResources=!0,this.loadStyles(function(){this._needsResources=!1,this.registerWhenReady()}.bind(this))}});e.publish(e.declaration,j),g(function(){document.body.removeAttribute("unresolved"),document.dispatchEvent(new CustomEvent("polymer-ready",{bubbles:!0}))}),document.registerElement("polymer-element",{prototype:j})}(Polymer),function(a){function b(a,b){a?(document.head.appendChild(a),d(b)):b&&b()}function c(a,c){if(a&&a.length){for(var d,e,f=document.createDocumentFragment(),g=0,h=a.length;h>g&&(d=a[g]);g++)e=document.createElement("link"),e.rel="import",e.href=d,f.appendChild(e);b(f,c)}else c&&c()}var d=a.whenReady;a["import"]=c,a.importElements=b}(Polymer),function(){var a=document.createElement("polymer-element");a.setAttribute("name","auto-binding"),a.setAttribute("extends","template"),a.init(),Polymer("auto-binding",{createdCallback:function(){this.syntax=this.bindingDelegate=this.makeSyntax(),Polymer.whenPolymerReady(function(){this.model=this,this.setAttribute("bind",""),this.async(function(){this.marshalNodeReferences(this.parentNode),this.fire("template-bound")})}.bind(this))},makeSyntax:function(){var a=Object.create(Polymer.api.declaration.events),b=this;a.findController=function(){return b.model};var c=new PolymerExpressions,d=c.prepareBinding;return c.prepareBinding=function(b,e,f){return a.prepareEventBinding(b,e,f)||d.call(c,b,e,f)},c}})}();
 window._TV_IS_COMPILED = true;
-'use strict';var global=this;this.tv=(function(){if(window.tv){console.warn('Base was multiply initialized. First init wins.');return window.tv;}
+'use strict';var global=this;this.tr=(function(){if(window.tr){console.warn('Base was multiply initialized. First init wins.');return window.tr;}
 function exportPath(name,opt_object,opt_objectToExportTo){var parts=name.split('.');var cur=opt_objectToExportTo||global;for(var part;parts.length&&(part=parts.shift());){if(!parts.length&&opt_object!==undefined){cur[part]=opt_object;}else if(part in cur){cur=cur[part];}else{cur=cur[part]={};}}
 return cur;};function isDefined(name,opt_globalObject){var parts=name.split('.');var curObject=opt_globalObject||global;for(var i=0;i<parts.length;i++){var partName=parts[i];var nextObject=curObject[partName];if(nextObject===undefined)
 return false;curObject=nextObject;}
@@ -1673,33 +1659,33 @@
 function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');}
 function exportTo(namespace,fn){var obj=exportPath(namespace);var exports=fn();for(var propertyName in exports){var propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor)
 Object.defineProperty(obj,propertyName,propertyDescriptor);}};function initialize(){if(!window._TRACE_VIEWER_IS_COMPILED){var ver=parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1],10);var support_content_shell=window.navigator.appVersion.match('77.34.5');if(ver<36&&!support_content_shell){var msg='A Chrome version of 36 or higher is required for '+'trace-viewer development. Please upgrade your version of Chrome '+'and try again.';showPanic('Invalid Chrome version',msg);}}
-tv.doc=document;tv.isMac=/Mac/.test(navigator.platform);tv.isWindows=/Win/.test(navigator.platform);tv.isChromeOS=/CrOS/.test(navigator.userAgent);tv.isLinux=/Linux/.test(navigator.userAgent);}
-return{initialize:initialize,exportTo:exportTo,isDefined:isDefined,showPanic:showPanic,hasPanic:hasPanic,getPanicText:getPanicText};})();tv.initialize();'use strict';tv.exportTo('tv.b.ui',function(){function decorate(source,constr){var elements;if(typeof source=='string')
-elements=tv.doc.querySelectorAll(source);else
+tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);}
+return{initialize:initialize,exportTo:exportTo,isDefined:isDefined,showPanic:showPanic,hasPanic:hasPanic,getPanicText:getPanicText};})();tr.initialize();'use strict';tr.exportTo('tr.b.ui',function(){function decorate(source,constr){var elements;if(typeof source=='string')
+elements=tr.doc.querySelectorAll(source);else
 elements=[source];for(var i=0,el;el=elements[i];i++){if(!(el instanceof constr))
 constr.decorate(el);}}
 function define(className,opt_parentConstructor,opt_tagNS){if(typeof className=='function'){throw new Error('Passing functions as className is deprecated. Please '+'use (className, opt_parentConstructor) to subclass');}
 var className=className.toLowerCase();if(opt_parentConstructor&&!opt_parentConstructor.tagName)
-throw new Error('opt_parentConstructor was not '+'created by tv.b.ui.define');var tagName=className;var tagNS=undefined;if(opt_parentConstructor){if(opt_tagNS)
+throw new Error('opt_parentConstructor was not '+'created by tr.b.ui.define');var tagName=className;var tagNS=undefined;if(opt_parentConstructor){if(opt_tagNS)
 throw new Error('Must not specify tagNS if parentConstructor is given');var parent=opt_parentConstructor;while(parent&&parent.tagName){tagName=parent.tagName;tagNS=parent.tagNS;parent=parent.parentConstructor;}}else{tagNS=opt_tagNS;}
 function f(){if(opt_parentConstructor&&f.prototype.__proto__!=opt_parentConstructor.prototype){throw new Error(className+' prototye\'s __proto__ field is messed up. '+'It MUST be the prototype of '+opt_parentConstructor.tagName);}
 var el;if(tagNS===undefined)
-el=tv.doc.createElement(tagName);else
-el=tv.doc.createElementNS(tagNS,tagName);f.decorate.call(this,el,arguments);return el;}
+el=tr.doc.createElement(tagName);else
+el=tr.doc.createElementNS(tagNS,tagName);f.decorate.call(this,el,arguments);return el;}
 f.decorate=function(el){el.__proto__=f.prototype;el.decorate.apply(el,arguments[1]);el.constructor=f;};f.className=className;f.tagName=tagName;f.tagNS=tagNS;f.parentConstructor=(opt_parentConstructor?opt_parentConstructor:undefined);f.toString=function(){if(!f.parentConstructor)
 return f.tagName;return f.parentConstructor.toString()+'::'+f.className;};return f;}
 function elementIsChildOf(el,potentialParent){if(el==potentialParent)
 return false;var cur=el;while(cur.parentNode){if(cur==potentialParent)
 return true;cur=cur.parentNode;}
-return false;};return{decorate:decorate,define:define,elementIsChildOf:elementIsChildOf};});'use strict';tv.exportTo('tv.b',function(){function asArray(arrayish){var values=[];for(var i=0;i<arrayish.length;i++)
+return false;};return{decorate:decorate,define:define,elementIsChildOf:elementIsChildOf};});'use strict';tr.exportTo('tr.b',function(){function asArray(arrayish){var values=[];for(var i=0;i<arrayish.length;i++)
 values.push(arrayish[i]);return values;}
 function compareArrays(x,y,elementCmp){var minLength=Math.min(x.length,y.length);for(var i=0;i<minLength;i++){var tmp=elementCmp(x[i],y[i]);if(tmp)
 return tmp;}
 if(x.length==y.length)
 return 0;if(x[i]===undefined)
 return-1;return 1;}
-function comparePossiblyUndefinedValues(x,y,cmp){if(x!==undefined&&y!==undefined)
-return cmp(x,y);if(x!==undefined)
+function comparePossiblyUndefinedValues(x,y,cmp,opt_this){if(x!==undefined&&y!==undefined)
+return cmp.call(opt_this,x,y);if(x!==undefined)
 return-1;if(y!==undefined)
 return 1;return 0;}
 function concatenateArrays(){var values=[];for(var i=0;i<arguments.length;i++){if(!(arguments[i]instanceof Array))
@@ -1713,6 +1699,9 @@
 values.push(dict[key]);return values;}
 function dictionaryLength(dict){var n=0;for(var key in dict)
 n++;return n;}
+function group(ary,fn){return ary.reduce(function(accumulator,curr){var key=fn(curr);if(key in accumulator)
+accumulator[key].push(curr);else
+accumulator[key]=[curr];return accumulator;},{});}
 function iterItems(dict,fn,opt_this){opt_this=opt_this||this;var keys=Object.keys(dict);for(var i=0;i<keys.length;i++){var key=keys[i];fn.call(opt_this,key,dict[key]);}}
 function mapItems(dict,fn,opt_this){opt_this=opt_this||this;var result={};var keys=Object.keys(dict);for(var i=0;i<keys.length;i++){var key=keys[i];result[key]=fn.call(opt_this,key,dict[key]);}
 return result;}
@@ -1726,18 +1715,22 @@
 return-1;}
 function findFirstInArray(ary,opt_func,opt_this){var i=findFirstIndexInArray(ary,opt_func,opt_func);if(i===-1)
 return undefined;return ary[i];}
-return{asArray:asArray,concatenateArrays:concatenateArrays,concatenateObjects:concatenateObjects,compareArrays:compareArrays,comparePossiblyUndefinedValues:comparePossiblyUndefinedValues,dictionaryLength:dictionaryLength,dictionaryKeys:dictionaryKeys,dictionaryValues:dictionaryValues,iterItems:iterItems,mapItems:mapItems,iterObjectFieldsRecursively:iterObjectFieldsRecursively,identity:identity,findFirstIndexInArray:findFirstIndexInArray,findFirstInArray:findFirstInArray};});(function(){"use strict";var e={};typeof exports=="undefined"?typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e.exports={},define(function(){return e.exports})):e.exports=window:e.exports=exports,function(e){if(!t)var t=1e-6;if(!n)var n=typeof Float32Array!="undefined"?Float32Array:Array;var r={};r.setMatrixArrayType=function(e){n=e},typeof e!="undefined"&&(e.glMatrix=r);var i={};i.create=function(){var e=new n(2);return e[0]=0,e[1]=0,e},i.clone=function(e){var t=new n(2);return t[0]=e[0],t[1]=e[1],t},i.fromValues=function(e,t){var r=new n(2);return r[0]=e,r[1]=t,r},i.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e},i.set=function(e,t,n){return e[0]=t,e[1]=n,e},i.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e},i.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e},i.sub=i.subtract,i.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e},i.mul=i.multiply,i.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e},i.div=i.divide,i.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e},i.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e},i.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e},i.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)},i.dist=i.distance,i.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return n*n+r*r},i.sqrDist=i.squaredDistance,i.length=function(e){var t=e[0],n=e[1];return Math.sqrt(t*t+n*n)},i.len=i.length,i.squaredLength=function(e){var t=e[0],n=e[1];return t*t+n*n},i.sqrLen=i.squaredLength,i.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e},i.normalize=function(e,t){var n=t[0],r=t[1],i=n*n+r*r;return i>0&&(i=1/Math.sqrt(i),e[0]=t[0]*i,e[1]=t[1]*i),e},i.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]},i.cross=function(e,t,n){var r=t[0]*n[1]-t[1]*n[0];return e[0]=e[1]=0,e[2]=r,e},i.lerp=function(e,t,n,r){var i=t[0],s=t[1];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e},i.transformMat2=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i,e[1]=n[1]*r+n[3]*i,e},i.transformMat2d=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i+n[4],e[1]=n[1]*r+n[3]*i+n[5],e},i.transformMat3=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[3]*i+n[6],e[1]=n[1]*r+n[4]*i+n[7],e},i.transformMat4=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[4]*i+n[12],e[1]=n[1]*r+n[5]*i+n[13],e},i.forEach=function(){var e=i.create();return function(t,n,r,i,s,o){var u,a;n||(n=2),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u<a;u+=n)e[0]=t[u],e[1]=t[u+1],s(e,e,o),t[u]=e[0],t[u+1]=e[1];return t}}(),i.str=function(e){return"vec2("+e[0]+", "+e[1]+")"},typeof e!="undefined"&&(e.vec2=i);var s={};s.create=function(){var e=new n(3);return e[0]=0,e[1]=0,e[2]=0,e},s.clone=function(e){var t=new n(3);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t},s.fromValues=function(e,t,r){var i=new n(3);return i[0]=e,i[1]=t,i[2]=r,i},s.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e},s.set=function(e,t,n,r){return e[0]=t,e[1]=n,e[2]=r,e},s.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e[2]=t[2]+n[2],e},s.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e[2]=t[2]-n[2],e},s.sub=s.subtract,s.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e[2]=t[2]*n[2],e},s.mul=s.multiply,s.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e[2]=t[2]/n[2],e},s.div=s.divide,s.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e},s.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e},s.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e},s.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2];return Math.sqrt(n*n+r*r+i*i)},s.dist=s.distance,s.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2];return n*n+r*r+i*i},s.sqrDist=s.squaredDistance,s.length=function(e){var t=e[0],n=e[1],r=e[2];return Math.sqrt(t*t+n*n+r*r)},s.len=s.length,s.squaredLength=function(e){var t=e[0],n=e[1],r=e[2];return t*t+n*n+r*r},s.sqrLen=s.squaredLength,s.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e},s.normalize=function(e,t){var n=t[0],r=t[1],i=t[2],s=n*n+r*r+i*i;return s>0&&(s=1/Math.sqrt(s),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s),e},s.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]},s.cross=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2];return e[0]=i*a-s*u,e[1]=s*o-r*a,e[2]=r*u-i*o,e},s.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e},s.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12],e[1]=n[1]*r+n[5]*i+n[9]*s+n[13],e[2]=n[2]*r+n[6]*i+n[10]*s+n[14],e},s.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},s.forEach=function(){var e=s.create();return function(t,n,r,i,s,o){var u,a;n||(n=3),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u<a;u+=n)e[0]=t[u],e[1]=t[u+1],e[2]=t[u+2],s(e,e,o),t[u]=e[0],t[u+1]=e[1],t[u+2]=e[2];return t}}(),s.str=function(e){return"vec3("+e[0]+", "+e[1]+", "+e[2]+")"},typeof e!="undefined"&&(e.vec3=s);var o={};o.create=function(){var e=new n(4);return e[0]=0,e[1]=0,e[2]=0,e[3]=0,e},o.clone=function(e){var t=new n(4);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},o.fromValues=function(e,t,r,i){var s=new n(4);return s[0]=e,s[1]=t,s[2]=r,s[3]=i,s},o.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e},o.set=function(e,t,n,r,i){return e[0]=t,e[1]=n,e[2]=r,e[3]=i,e},o.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e[2]=t[2]+n[2],e[3]=t[3]+n[3],e},o.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e[2]=t[2]-n[2],e[3]=t[3]-n[3],e},o.sub=o.subtract,o.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e[2]=t[2]*n[2],e[3]=t[3]*n[3],e},o.mul=o.multiply,o.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e[2]=t[2]/n[2],e[3]=t[3]/n[3],e},o.div=o.divide,o.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e[3]=Math.min(t[3],n[3]),e},o.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e[3]=Math.max(t[3],n[3]),e},o.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e[3]=t[3]*n,e},o.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2],s=t[3]-e[3];return Math.sqrt(n*n+r*r+i*i+s*s)},o.dist=o.distance,o.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2],s=t[3]-e[3];return n*n+r*r+i*i+s*s},o.sqrDist=o.squaredDistance,o.length=function(e){var t=e[0],n=e[1],r=e[2],i=e[3];return Math.sqrt(t*t+n*n+r*r+i*i)},o.len=o.length,o.squaredLength=function(e){var t=e[0],n=e[1],r=e[2],i=e[3];return t*t+n*n+r*r+i*i},o.sqrLen=o.squaredLength,o.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e[3]=-t[3],e},o.normalize=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*n+r*r+i*i+s*s;return o>0&&(o=1/Math.sqrt(o),e[0]=t[0]*o,e[1]=t[1]*o,e[2]=t[2]*o,e[3]=t[3]*o),e},o.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]},o.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e[3]=u+r*(n[3]-u),e},o.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12]*o,e[1]=n[1]*r+n[5]*i+n[9]*s+n[13]*o,e[2]=n[2]*r+n[6]*i+n[10]*s+n[14]*o,e[3]=n[3]*r+n[7]*i+n[11]*s+n[15]*o,e},o.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},o.forEach=function(){var e=o.create();return function(t,n,r,i,s,o){var u,a;n||(n=4),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u<a;u+=n)e[0]=t[u],e[1]=t[u+1],e[2]=t[u+2],e[3]=t[u+3],s(e,e,o),t[u]=e[0],t[u+1]=e[1],t[u+2]=e[2],t[u+3]=e[3];return t}}(),o.str=function(e){return"vec4("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.vec4=o);var u={};u.create=function(){var e=new n(4);return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e},u.clone=function(e){var t=new n(4);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},u.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e},u.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e},u.transpose=function(e,t){if(e===t){var n=t[1];e[1]=t[2],e[2]=n}else e[0]=t[0],e[1]=t[2],e[2]=t[1],e[3]=t[3];return e},u.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*s-i*r;return o?(o=1/o,e[0]=s*o,e[1]=-r*o,e[2]=-i*o,e[3]=n*o,e):null},u.adjoint=function(e,t){var n=t[0];return e[0]=t[3],e[1]=-t[1],e[2]=-t[2],e[3]=n,e},u.determinant=function(e){return e[0]*e[3]-e[2]*e[1]},u.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1],f=n[2],l=n[3];return e[0]=r*u+i*f,e[1]=r*a+i*l,e[2]=s*u+o*f,e[3]=s*a+o*l,e},u.mul=u.multiply,u.rotate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+i*u,e[1]=r*-u+i*a,e[2]=s*a+o*u,e[3]=s*-u+o*a,e},u.scale=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1];return e[0]=r*u,e[1]=i*a,e[2]=s*u,e[3]=o*a,e},u.str=function(e){return"mat2("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.mat2=u);var a={};a.create=function(){var e=new n(6);return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e[4]=0,e[5]=0,e},a.clone=function(e){var t=new n(6);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t},a.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e},a.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e[4]=0,e[5]=0,e},a.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=n*s-r*i;return a?(a=1/a,e[0]=s*a,e[1]=-r*a,e[2]=-i*a,e[3]=n*a,e[4]=(i*u-s*o)*a,e[5]=(r*o-n*u)*a,e):null},a.determinant=function(e){return e[0]*e[3]-e[1]*e[2]},a.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=n[0],l=n[1],c=n[2],h=n[3],p=n[4],d=n[5];return e[0]=r*f+i*c,e[1]=r*l+i*h,e[2]=s*f+o*c,e[3]=s*l+o*h,e[4]=f*u+c*a+p,e[5]=l*u+h*a+d,e},a.mul=a.multiply,a.rotate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=Math.sin(n),l=Math.cos(n);return e[0]=r*l+i*f,e[1]=-r*f+i*l,e[2]=s*l+o*f,e[3]=-s*f+l*o,e[4]=l*u+f*a,e[5]=l*a-f*u,e},a.scale=function(e,t,n){var r=n[0],i=n[1];return e[0]=t[0]*r,e[1]=t[1]*i,e[2]=t[2]*r,e[3]=t[3]*i,e[4]=t[4]*r,e[5]=t[5]*i,e},a.translate=function(e,t,n){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4]+n[0],e[5]=t[5]+n[1],e},a.str=function(e){return"mat2d("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+")"},typeof e!="undefined"&&(e.mat2d=a);var f={};f.create=function(){var e=new n(9);return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=1,e[5]=0,e[6]=0,e[7]=0,e[8]=1,e},f.fromMat4=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[4],e[4]=t[5],e[5]=t[6],e[6]=t[8],e[7]=t[9],e[8]=t[10],e},f.clone=function(e){var t=new n(9);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t},f.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e},f.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=1,e[5]=0,e[6]=0,e[7]=0,e[8]=1,e},f.transpose=function(e,t){if(e===t){var n=t[1],r=t[2],i=t[5];e[1]=t[3],e[2]=t[6],e[3]=n,e[5]=t[7],e[6]=r,e[7]=i}else e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8];return e},f.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8],c=l*o-u*f,h=-l*s+u*a,p=f*s-o*a,d=n*c+r*h+i*p;return d?(d=1/d,e[0]=c*d,e[1]=(-l*r+i*f)*d,e[2]=(u*r-i*o)*d,e[3]=h*d,e[4]=(l*n-i*a)*d,e[5]=(-u*n+i*s)*d,e[6]=p*d,e[7]=(-f*n+r*a)*d,e[8]=(o*n-r*s)*d,e):null},f.adjoint=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8];return e[0]=o*l-u*f,e[1]=i*f-r*l,e[2]=r*u-i*o,e[3]=u*a-s*l,e[4]=n*l-i*a,e[5]=i*s-n*u,e[6]=s*f-o*a,e[7]=r*a-n*f,e[8]=n*o-r*s,e},f.determinant=function(e){var t=e[0],n=e[1],r=e[2],i=e[3],s=e[4],o=e[5],u=e[6],a=e[7],f=e[8];return t*(f*s-o*a)+n*(-f*i+o*u)+r*(a*i-s*u)},f.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=n[0],p=n[1],d=n[2],v=n[3],m=n[4],g=n[5],y=n[6],b=n[7],w=n[8];return e[0]=h*r+p*o+d*f,e[1]=h*i+p*u+d*l,e[2]=h*s+p*a+d*c,e[3]=v*r+m*o+g*f,e[4]=v*i+m*u+g*l,e[5]=v*s+m*a+g*c,e[6]=y*r+b*o+w*f,e[7]=y*i+b*u+w*l,e[8]=y*s+b*a+w*c,e},f.mul=f.multiply,f.translate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=n[0],p=n[1];return e[0]=r,e[1]=i,e[2]=s,e[3]=o,e[4]=u,e[5]=a,e[6]=h*r+p*o+f,e[7]=h*i+p*u+l,e[8]=h*s+p*a+c,e},f.rotate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=Math.sin(n),p=Math.cos(n);return e[0]=p*r+h*o,e[1]=p*i+h*u,e[2]=p*s+h*a,e[3]=p*o-h*r,e[4]=p*u-h*i,e[5]=p*a-h*s,e[6]=f,e[7]=l,e[8]=c,e},f.scale=function(e,t,n){var r=n[0],i=n[2];return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=i*t[3],e[4]=i*t[4],e[5]=i*t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e},f.fromMat2d=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=0,e[3]=t[2],e[4]=t[3],e[5]=0,e[6]=t[4],e[7]=t[5],e[8]=1,e},f.fromQuat=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n+n,u=r+r,a=i+i,f=n*o,l=n*u,c=n*a,h=r*u,p=r*a,d=i*a,v=s*o,m=s*u,g=s*a;return e[0]=1-(h+d),e[1]=l+g,e[2]=c-m,e[3]=l-g,e[4]=1-(f+d),e[5]=p+v,e[6]=c+m,e[7]=p-v,e[8]=1-(f+h),e},f.str=function(e){return"mat3("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+", "+e[6]+", "+e[7]+", "+e[8]+")"},typeof e!="undefined"&&(e.mat3=f);var l={};l.create=function(){var e=new n(16);return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},l.clone=function(e){var t=new n(16);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t[9]=e[9],t[10]=e[10],t[11]=e[11],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t},l.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e},l.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},l.transpose=function(e,t){if(e===t){var n=t[1],r=t[2],i=t[3],s=t[6],o=t[7],u=t[11];e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=n,e[6]=t[9],e[7]=t[13],e[8]=r,e[9]=s,e[11]=t[14],e[12]=i,e[13]=o,e[14]=u}else e[0]=t[0],e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=t[1],e[5]=t[5],e[6]=t[9],e[7]=t[13],e[8]=t[2],e[9]=t[6],e[10]=t[10],e[11]=t[14],e[12]=t[3],e[13]=t[7],e[14]=t[11],e[15]=t[15];return e},l.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8],c=t[9],h=t[10],p=t[11],d=t[12],v=t[13],m=t[14],g=t[15],y=n*u-r*o,b=n*a-i*o,w=n*f-s*o,E=r*a-i*u,S=r*f-s*u,x=i*f-s*a,T=l*v-c*d,N=l*m-h*d,C=l*g-p*d,k=c*m-h*v,L=c*g-p*v,A=h*g-p*m,O=y*A-b*L+w*k+E*C-S*N+x*T;return O?(O=1/O,e[0]=(u*A-a*L+f*k)*O,e[1]=(i*L-r*A-s*k)*O,e[2]=(v*x-m*S+g*E)*O,e[3]=(h*S-c*x-p*E)*O,e[4]=(a*C-o*A-f*N)*O,e[5]=(n*A-i*C+s*N)*O,e[6]=(m*w-d*x-g*b)*O,e[7]=(l*x-h*w+p*b)*O,e[8]=(o*L-u*C+f*T)*O,e[9]=(r*C-n*L-s*T)*O,e[10]=(d*S-v*w+g*y)*O,e[11]=(c*w-l*S-p*y)*O,e[12]=(u*N-o*k-a*T)*O,e[13]=(n*k-r*N+i*T)*O,e[14]=(v*b-d*E-m*y)*O,e[15]=(l*E-c*b+h*y)*O,e):null},l.adjoint=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8],c=t[9],h=t[10],p=t[11],d=t[12],v=t[13],m=t[14],g=t[15];return e[0]=u*(h*g-p*m)-c*(a*g-f*m)+v*(a*p-f*h),e[1]=-(r*(h*g-p*m)-c*(i*g-s*m)+v*(i*p-s*h)),e[2]=r*(a*g-f*m)-u*(i*g-s*m)+v*(i*f-s*a),e[3]=-(r*(a*p-f*h)-u*(i*p-s*h)+c*(i*f-s*a)),e[4]=-(o*(h*g-p*m)-l*(a*g-f*m)+d*(a*p-f*h)),e[5]=n*(h*g-p*m)-l*(i*g-s*m)+d*(i*p-s*h),e[6]=-(n*(a*g-f*m)-o*(i*g-s*m)+d*(i*f-s*a)),e[7]=n*(a*p-f*h)-o*(i*p-s*h)+l*(i*f-s*a),e[8]=o*(c*g-p*v)-l*(u*g-f*v)+d*(u*p-f*c),e[9]=-(n*(c*g-p*v)-l*(r*g-s*v)+d*(r*p-s*c)),e[10]=n*(u*g-f*v)-o*(r*g-s*v)+d*(r*f-s*u),e[11]=-(n*(u*p-f*c)-o*(r*p-s*c)+l*(r*f-s*u)),e[12]=-(o*(c*m-h*v)-l*(u*m-a*v)+d*(u*h-a*c)),e[13]=n*(c*m-h*v)-l*(r*m-i*v)+d*(r*h-i*c),e[14]=-(n*(u*m-a*v)-o*(r*m-i*v)+d*(r*a-i*u)),e[15]=n*(u*h-a*c)-o*(r*h-i*c)+l*(r*a-i*u),e},l.determinant=function(e){var t=e[0],n=e[1],r=e[2],i=e[3],s=e[4],o=e[5],u=e[6],a=e[7],f=e[8],l=e[9],c=e[10],h=e[11],p=e[12],d=e[13],v=e[14],m=e[15],g=t*o-n*s,y=t*u-r*s,b=t*a-i*s,w=n*u-r*o,E=n*a-i*o,S=r*a-i*u,x=f*d-l*p,T=f*v-c*p,N=f*m-h*p,C=l*v-c*d,k=l*m-h*d,L=c*m-h*v;return g*L-y*k+b*C+w*N-E*T+S*x},l.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=t[9],p=t[10],d=t[11],v=t[12],m=t[13],g=t[14],y=t[15],b=n[0],w=n[1],E=n[2],S=n[3];return e[0]=b*r+w*u+E*c+S*v,e[1]=b*i+w*a+E*h+S*m,e[2]=b*s+w*f+E*p+S*g,e[3]=b*o+w*l+E*d+S*y,b=n[4],w=n[5],E=n[6],S=n[7],e[4]=b*r+w*u+E*c+S*v,e[5]=b*i+w*a+E*h+S*m,e[6]=b*s+w*f+E*p+S*g,e[7]=b*o+w*l+E*d+S*y,b=n[8],w=n[9],E=n[10],S=n[11],e[8]=b*r+w*u+E*c+S*v,e[9]=b*i+w*a+E*h+S*m,e[10]=b*s+w*f+E*p+S*g,e[11]=b*o+w*l+E*d+S*y,b=n[12],w=n[13],E=n[14],S=n[15],e[12]=b*r+w*u+E*c+S*v,e[13]=b*i+w*a+E*h+S*m,e[14]=b*s+w*f+E*p+S*g,e[15]=b*o+w*l+E*d+S*y,e},l.mul=l.multiply,l.translate=function(e,t,n){var r=n[0],i=n[1],s=n[2],o,u,a,f,l,c,h,p,d,v,m,g;return t===e?(e[12]=t[0]*r+t[4]*i+t[8]*s+t[12],e[13]=t[1]*r+t[5]*i+t[9]*s+t[13],e[14]=t[2]*r+t[6]*i+t[10]*s+t[14],e[15]=t[3]*r+t[7]*i+t[11]*s+t[15]):(o=t[0],u=t[1],a=t[2],f=t[3],l=t[4],c=t[5],h=t[6],p=t[7],d=t[8],v=t[9],m=t[10],g=t[11],e[0]=o,e[1]=u,e[2]=a,e[3]=f,e[4]=l,e[5]=c,e[6]=h,e[7]=p,e[8]=d,e[9]=v,e[10]=m,e[11]=g,e[12]=o*r+l*i+d*s+t[12],e[13]=u*r+c*i+v*s+t[13],e[14]=a*r+h*i+m*s+t[14],e[15]=f*r+p*i+g*s+t[15]),e},l.scale=function(e,t,n){var r=n[0],i=n[1],s=n[2];return e[0]=t[0]*r,e[1]=t[1]*r,e[2]=t[2]*r,e[3]=t[3]*r,e[4]=t[4]*i,e[5]=t[5]*i,e[6]=t[6]*i,e[7]=t[7]*i,e[8]=t[8]*s,e[9]=t[9]*s,e[10]=t[10]*s,e[11]=t[11]*s,e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e},l.rotate=function(e,n,r,i){var s=i[0],o=i[1],u=i[2],a=Math.sqrt(s*s+o*o+u*u),f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_;return Math.abs(a)<t?null:(a=1/a,s*=a,o*=a,u*=a,f=Math.sin(r),l=Math.cos(r),c=1-l,h=n[0],p=n[1],d=n[2],v=n[3],m=n[4],g=n[5],y=n[6],b=n[7],w=n[8],E=n[9],S=n[10],x=n[11],T=s*s*c+l,N=o*s*c+u*f,C=u*s*c-o*f,k=s*o*c-u*f,L=o*o*c+l,A=u*o*c+s*f,O=s*u*c+o*f,M=o*u*c-s*f,_=u*u*c+l,e[0]=h*T+m*N+w*C,e[1]=p*T+g*N+E*C,e[2]=d*T+y*N+S*C,e[3]=v*T+b*N+x*C,e[4]=h*k+m*L+w*A,e[5]=p*k+g*L+E*A,e[6]=d*k+y*L+S*A,e[7]=v*k+b*L+x*A,e[8]=h*O+m*M+w*_,e[9]=p*O+g*M+E*_,e[10]=d*O+y*M+S*_,e[11]=v*O+b*M+x*_,n!==e&&(e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15]),e)},l.rotateX=function(e,t,n){var r=Math.sin(n),i=Math.cos(n),s=t[4],o=t[5],u=t[6],a=t[7],f=t[8],l=t[9],c=t[10],h=t[11];return t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[4]=s*i+f*r,e[5]=o*i+l*r,e[6]=u*i+c*r,e[7]=a*i+h*r,e[8]=f*i-s*r,e[9]=l*i-o*r,e[10]=c*i-u*r,e[11]=h*i-a*r,e},l.rotateY=function(e,t,n){var r=Math.sin(n),i=Math.cos(n),s=t[0],o=t[1],u=t[2],a=t[3],f=t[8],l=t[9],c=t[10],h=t[11];return t!==e&&(e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=s*i-f*r,e[1]=o*i-l*r,e[2]=u*i-c*r,e[3]=a*i-h*r,e[8]=s*r+f*i,e[9]=o*r+l*i,e[10]=u*r+c*i,e[11]=a*r+h*i,e},l.rotateZ=function(e,t,n){var r=Math.sin(n),i=Math.cos(n),s=t[0],o=t[1],u=t[2],a=t[3],f=t[4],l=t[5],c=t[6],h=t[7];return t!==e&&(e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=s*i+f*r,e[1]=o*i+l*r,e[2]=u*i+c*r,e[3]=a*i+h*r,e[4]=f*i-s*r,e[5]=l*i-o*r,e[6]=c*i-u*r,e[7]=h*i-a*r,e},l.fromRotationTranslation=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=r+r,a=i+i,f=s+s,l=r*u,c=r*a,h=r*f,p=i*a,d=i*f,v=s*f,m=o*u,g=o*a,y=o*f;return e[0]=1-(p+v),e[1]=c+y,e[2]=h-g,e[3]=0,e[4]=c-y,e[5]=1-(l+v),e[6]=d+m,e[7]=0,e[8]=h+g,e[9]=d-m,e[10]=1-(l+p),e[11]=0,e[12]=n[0],e[13]=n[1],e[14]=n[2],e[15]=1,e},l.fromQuat=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n+n,u=r+r,a=i+i,f=n*o,l=n*u,c=n*a,h=r*u,p=r*a,d=i*a,v=s*o,m=s*u,g=s*a;return e[0]=1-(h+d),e[1]=l+g,e[2]=c-m,e[3]=0,e[4]=l-g,e[5]=1-(f+d),e[6]=p+v,e[7]=0,e[8]=c+m,e[9]=p-v,e[10]=1-(f+h),e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},l.frustum=function(e,t,n,r,i,s,o){var u=1/(n-t),a=1/(i-r),f=1/(s-o);return e[0]=s*2*u,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=s*2*a,e[6]=0,e[7]=0,e[8]=(n+t)*u,e[9]=(i+r)*a,e[10]=(o+s)*f,e[11]=-1,e[12]=0,e[13]=0,e[14]=o*s*2*f,e[15]=0,e},l.perspective=function(e,t,n,r,i){var s=1/Math.tan(t/2),o=1/(r-i);return e[0]=s/n,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=s,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=(i+r)*o,e[11]=-1,e[12]=0,e[13]=0,e[14]=2*i*r*o,e[15]=0,e},l.ortho=function(e,t,n,r,i,s,o){var u=1/(t-n),a=1/(r-i),f=1/(s-o);return e[0]=-2*u,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=-2*a,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=2*f,e[11]=0,e[12]=(t+n)*u,e[13]=(i+r)*a,e[14]=(o+s)*f,e[15]=1,e},l.lookAt=function(e,n,r,i){var s,o,u,a,f,c,h,p,d,v,m=n[0],g=n[1],y=n[2],b=i[0],w=i[1],E=i[2],S=r[0],x=r[1],T=r[2];return Math.abs(m-S)<t&&Math.abs(g-x)<t&&Math.abs(y-T)<t?l.identity(e):(h=m-S,p=g-x,d=y-T,v=1/Math.sqrt(h*h+p*p+d*d),h*=v,p*=v,d*=v,s=w*d-E*p,o=E*h-b*d,u=b*p-w*h,v=Math.sqrt(s*s+o*o+u*u),v?(v=1/v,s*=v,o*=v,u*=v):(s=0,o=0,u=0),a=p*u-d*o,f=d*s-h*u,c=h*o-p*s,v=Math.sqrt(a*a+f*f+c*c),v?(v=1/v,a*=v,f*=v,c*=v):(a=0,f=0,c=0),e[0]=s,e[1]=a,e[2]=h,e[3]=0,e[4]=o,e[5]=f,e[6]=p,e[7]=0,e[8]=u,e[9]=c,e[10]=d,e[11]=0,e[12]=-(s*m+o*g+u*y),e[13]=-(a*m+f*g+c*y),e[14]=-(h*m+p*g+d*y),e[15]=1,e)},l.str=function(e){return"mat4("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+", "+e[6]+", "+e[7]+", "+e[8]+", "+e[9]+", "+e[10]+", "+e[11]+", "+e[12]+", "+e[13]+", "+e[14]+", "+e[15]+")"},typeof e!="undefined"&&(e.mat4=l);var c={};c.create=function(){var e=new n(4);return e[0]=0,e[1]=0,e[2]=0,e[3]=1,e},c.clone=o.clone,c.fromValues=o.fromValues,c.copy=o.copy,c.set=o.set,c.identity=function(e){return e[0]=0,e[1]=0,e[2]=0,e[3]=1,e},c.setAxisAngle=function(e,t,n){n*=.5;var r=Math.sin(n);return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=Math.cos(n),e},c.add=o.add,c.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1],f=n[2],l=n[3];return e[0]=r*l+o*u+i*f-s*a,e[1]=i*l+o*a+s*u-r*f,e[2]=s*l+o*f+r*a-i*u,e[3]=o*l-r*u-i*a-s*f,e},c.mul=c.multiply,c.scale=o.scale,c.rotateX=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+o*u,e[1]=i*a+s*u,e[2]=s*a-i*u,e[3]=o*a-r*u,e},c.rotateY=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a-s*u,e[1]=i*a+o*u,e[2]=s*a+r*u,e[3]=o*a-i*u,e},c.rotateZ=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+i*u,e[1]=i*a-r*u,e[2]=s*a+o*u,e[3]=o*a-s*u,e},c.calculateW=function(e,t){var n=t[0],r=t[1],i=t[2];return e[0]=n,e[1]=r,e[2]=i,e[3]=-Math.sqrt(Math.abs(1-n*n-r*r-i*i)),e},c.dot=o.dot,c.lerp=o.lerp,c.slerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3],a=n[0],f=n[1],l=n[2],c=n[3],h=i*a+s*f+o*l+u*c,p,d,v,m;return Math.abs(h)>=1?(e!==t&&(e[0]=i,e[1]=s,e[2]=o,e[3]=u),e):(p=Math.acos(h),d=Math.sqrt(1-h*h),Math.abs(d)<.001?(e[0]=i*.5+a*.5,e[1]=s*.5+f*.5,e[2]=o*.5+l*.5,e[3]=u*.5+c*.5,e):(v=Math.sin((1-r)*p)/d,m=Math.sin(r*p)/d,e[0]=i*v+a*m,e[1]=s*v+f*m,e[2]=o*v+l*m,e[3]=u*v+c*m,e))},c.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*n+r*r+i*i+s*s,u=o?1/o:0;return e[0]=-n*u,e[1]=-r*u,e[2]=-i*u,e[3]=s*u,e},c.conjugate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e[3]=t[3],e},c.length=o.length,c.len=c.length,c.squaredLength=o.squaredLength,c.sqrLen=c.squaredLength,c.normalize=o.normalize,c.fromMat3=function(){var e=[1,2,0];return function(t,n){var r=n[0]+n[4]+n[8],i;if(r>0)i=Math.sqrt(r+1),t[3]=.5*i,i=.5/i,t[0]=(n[7]-n[5])*i,t[1]=(n[2]-n[6])*i,t[2]=(n[3]-n[1])*i;else{var s=0;n[4]>n[0]&&(s=1),n[8]>n[s*3+s]&&(s=2);var o=e[s],u=e[o];i=Math.sqrt(n[s*3+s]-n[o*3+o]-n[u*3+u]+1),t[s]=.5*i,i=.5/i,t[3]=(n[u*3+o]-n[o*3+u])*i,t[o]=(n[o*3+s]+n[s*3+o])*i,t[u]=(n[u*3+s]+n[s*3+u])*i}return t}}(),c.str=function(e){return"quat("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.quat=c)}(e.exports)})();'use strict';tv.exportTo('tv.b',function(){var tmp_vec2=vec2.create();var tmp_vec2b=vec2.create();var tmp_vec4=vec4.create();var tmp_mat2d=mat2d.create();vec2.createFromArray=function(arr){if(arr.length!=2)
-throw new Error('Should be length 2');var v=vec2.create();vec2.set(v,arr[0],arr[1]);return v;};vec2.createXY=function(x,y){var v=vec2.create();vec2.set(v,x,y);return v;};vec2.toString=function(a){return'['+a[0]+', '+a[1]+']';};vec2.addTwoScaledUnitVectors=function(out,u1,scale1,u2,scale2){vec2.scale(tmp_vec2,u1,scale1);vec2.scale(tmp_vec2b,u2,scale2);vec2.add(out,tmp_vec2,tmp_vec2b);}
-vec3.createXYZ=function(x,y,z){var v=vec3.create();vec3.set(v,x,y,z);return v;};vec3.toString=function(a){return'vec3('+a[0]+', '+a[1]+', '+a[2]+')';}
+return{asArray:asArray,concatenateArrays:concatenateArrays,concatenateObjects:concatenateObjects,compareArrays:compareArrays,comparePossiblyUndefinedValues:comparePossiblyUndefinedValues,dictionaryLength:dictionaryLength,dictionaryKeys:dictionaryKeys,dictionaryValues:dictionaryValues,group:group,iterItems:iterItems,mapItems:mapItems,iterObjectFieldsRecursively:iterObjectFieldsRecursively,identity:identity,findFirstIndexInArray:findFirstIndexInArray,findFirstInArray:findFirstInArray};});(function(){"use strict";var e={};typeof exports=="undefined"?typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e.exports={},define(function(){return e.exports})):e.exports=window:e.exports=exports,function(e){if(!t)var t=1e-6;if(!n)var n=typeof Float32Array!="undefined"?Float32Array:Array;var r={};r.setMatrixArrayType=function(e){n=e},typeof e!="undefined"&&(e.glMatrix=r);var i={};i.create=function(){var e=new n(2);return e[0]=0,e[1]=0,e},i.clone=function(e){var t=new n(2);return t[0]=e[0],t[1]=e[1],t},i.fromValues=function(e,t){var r=new n(2);return r[0]=e,r[1]=t,r},i.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e},i.set=function(e,t,n){return e[0]=t,e[1]=n,e},i.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e},i.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e},i.sub=i.subtract,i.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e},i.mul=i.multiply,i.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e},i.div=i.divide,i.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e},i.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e},i.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e},i.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)},i.dist=i.distance,i.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return n*n+r*r},i.sqrDist=i.squaredDistance,i.length=function(e){var t=e[0],n=e[1];return Math.sqrt(t*t+n*n)},i.len=i.length,i.squaredLength=function(e){var t=e[0],n=e[1];return t*t+n*n},i.sqrLen=i.squaredLength,i.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e},i.normalize=function(e,t){var n=t[0],r=t[1],i=n*n+r*r;return i>0&&(i=1/Math.sqrt(i),e[0]=t[0]*i,e[1]=t[1]*i),e},i.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]},i.cross=function(e,t,n){var r=t[0]*n[1]-t[1]*n[0];return e[0]=e[1]=0,e[2]=r,e},i.lerp=function(e,t,n,r){var i=t[0],s=t[1];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e},i.transformMat2=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i,e[1]=n[1]*r+n[3]*i,e},i.transformMat2d=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i+n[4],e[1]=n[1]*r+n[3]*i+n[5],e},i.transformMat3=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[3]*i+n[6],e[1]=n[1]*r+n[4]*i+n[7],e},i.transformMat4=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[4]*i+n[12],e[1]=n[1]*r+n[5]*i+n[13],e},i.forEach=function(){var e=i.create();return function(t,n,r,i,s,o){var u,a;n||(n=2),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u<a;u+=n)e[0]=t[u],e[1]=t[u+1],s(e,e,o),t[u]=e[0],t[u+1]=e[1];return t}}(),i.str=function(e){return"vec2("+e[0]+", "+e[1]+")"},typeof e!="undefined"&&(e.vec2=i);var s={};s.create=function(){var e=new n(3);return e[0]=0,e[1]=0,e[2]=0,e},s.clone=function(e){var t=new n(3);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t},s.fromValues=function(e,t,r){var i=new n(3);return i[0]=e,i[1]=t,i[2]=r,i},s.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e},s.set=function(e,t,n,r){return e[0]=t,e[1]=n,e[2]=r,e},s.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e[2]=t[2]+n[2],e},s.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e[2]=t[2]-n[2],e},s.sub=s.subtract,s.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e[2]=t[2]*n[2],e},s.mul=s.multiply,s.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e[2]=t[2]/n[2],e},s.div=s.divide,s.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e},s.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e},s.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e},s.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2];return Math.sqrt(n*n+r*r+i*i)},s.dist=s.distance,s.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2];return n*n+r*r+i*i},s.sqrDist=s.squaredDistance,s.length=function(e){var t=e[0],n=e[1],r=e[2];return Math.sqrt(t*t+n*n+r*r)},s.len=s.length,s.squaredLength=function(e){var t=e[0],n=e[1],r=e[2];return t*t+n*n+r*r},s.sqrLen=s.squaredLength,s.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e},s.normalize=function(e,t){var n=t[0],r=t[1],i=t[2],s=n*n+r*r+i*i;return s>0&&(s=1/Math.sqrt(s),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s),e},s.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]},s.cross=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2];return e[0]=i*a-s*u,e[1]=s*o-r*a,e[2]=r*u-i*o,e},s.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e},s.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12],e[1]=n[1]*r+n[5]*i+n[9]*s+n[13],e[2]=n[2]*r+n[6]*i+n[10]*s+n[14],e},s.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},s.forEach=function(){var e=s.create();return function(t,n,r,i,s,o){var u,a;n||(n=3),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u<a;u+=n)e[0]=t[u],e[1]=t[u+1],e[2]=t[u+2],s(e,e,o),t[u]=e[0],t[u+1]=e[1],t[u+2]=e[2];return t}}(),s.str=function(e){return"vec3("+e[0]+", "+e[1]+", "+e[2]+")"},typeof e!="undefined"&&(e.vec3=s);var o={};o.create=function(){var e=new n(4);return e[0]=0,e[1]=0,e[2]=0,e[3]=0,e},o.clone=function(e){var t=new n(4);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},o.fromValues=function(e,t,r,i){var s=new n(4);return s[0]=e,s[1]=t,s[2]=r,s[3]=i,s},o.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e},o.set=function(e,t,n,r,i){return e[0]=t,e[1]=n,e[2]=r,e[3]=i,e},o.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e[2]=t[2]+n[2],e[3]=t[3]+n[3],e},o.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e[2]=t[2]-n[2],e[3]=t[3]-n[3],e},o.sub=o.subtract,o.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e[2]=t[2]*n[2],e[3]=t[3]*n[3],e},o.mul=o.multiply,o.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e[2]=t[2]/n[2],e[3]=t[3]/n[3],e},o.div=o.divide,o.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e[3]=Math.min(t[3],n[3]),e},o.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e[3]=Math.max(t[3],n[3]),e},o.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e[3]=t[3]*n,e},o.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2],s=t[3]-e[3];return Math.sqrt(n*n+r*r+i*i+s*s)},o.dist=o.distance,o.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2],s=t[3]-e[3];return n*n+r*r+i*i+s*s},o.sqrDist=o.squaredDistance,o.length=function(e){var t=e[0],n=e[1],r=e[2],i=e[3];return Math.sqrt(t*t+n*n+r*r+i*i)},o.len=o.length,o.squaredLength=function(e){var t=e[0],n=e[1],r=e[2],i=e[3];return t*t+n*n+r*r+i*i},o.sqrLen=o.squaredLength,o.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e[3]=-t[3],e},o.normalize=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*n+r*r+i*i+s*s;return o>0&&(o=1/Math.sqrt(o),e[0]=t[0]*o,e[1]=t[1]*o,e[2]=t[2]*o,e[3]=t[3]*o),e},o.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]},o.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e[3]=u+r*(n[3]-u),e},o.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12]*o,e[1]=n[1]*r+n[5]*i+n[9]*s+n[13]*o,e[2]=n[2]*r+n[6]*i+n[10]*s+n[14]*o,e[3]=n[3]*r+n[7]*i+n[11]*s+n[15]*o,e},o.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},o.forEach=function(){var e=o.create();return function(t,n,r,i,s,o){var u,a;n||(n=4),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u<a;u+=n)e[0]=t[u],e[1]=t[u+1],e[2]=t[u+2],e[3]=t[u+3],s(e,e,o),t[u]=e[0],t[u+1]=e[1],t[u+2]=e[2],t[u+3]=e[3];return t}}(),o.str=function(e){return"vec4("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.vec4=o);var u={};u.create=function(){var e=new n(4);return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e},u.clone=function(e){var t=new n(4);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},u.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e},u.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e},u.transpose=function(e,t){if(e===t){var n=t[1];e[1]=t[2],e[2]=n}else e[0]=t[0],e[1]=t[2],e[2]=t[1],e[3]=t[3];return e},u.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*s-i*r;return o?(o=1/o,e[0]=s*o,e[1]=-r*o,e[2]=-i*o,e[3]=n*o,e):null},u.adjoint=function(e,t){var n=t[0];return e[0]=t[3],e[1]=-t[1],e[2]=-t[2],e[3]=n,e},u.determinant=function(e){return e[0]*e[3]-e[2]*e[1]},u.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1],f=n[2],l=n[3];return e[0]=r*u+i*f,e[1]=r*a+i*l,e[2]=s*u+o*f,e[3]=s*a+o*l,e},u.mul=u.multiply,u.rotate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+i*u,e[1]=r*-u+i*a,e[2]=s*a+o*u,e[3]=s*-u+o*a,e},u.scale=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1];return e[0]=r*u,e[1]=i*a,e[2]=s*u,e[3]=o*a,e},u.str=function(e){return"mat2("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.mat2=u);var a={};a.create=function(){var e=new n(6);return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e[4]=0,e[5]=0,e},a.clone=function(e){var t=new n(6);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t},a.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e},a.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=1,e[4]=0,e[5]=0,e},a.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=n*s-r*i;return a?(a=1/a,e[0]=s*a,e[1]=-r*a,e[2]=-i*a,e[3]=n*a,e[4]=(i*u-s*o)*a,e[5]=(r*o-n*u)*a,e):null},a.determinant=function(e){return e[0]*e[3]-e[1]*e[2]},a.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=n[0],l=n[1],c=n[2],h=n[3],p=n[4],d=n[5];return e[0]=r*f+i*c,e[1]=r*l+i*h,e[2]=s*f+o*c,e[3]=s*l+o*h,e[4]=f*u+c*a+p,e[5]=l*u+h*a+d,e},a.mul=a.multiply,a.rotate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=Math.sin(n),l=Math.cos(n);return e[0]=r*l+i*f,e[1]=-r*f+i*l,e[2]=s*l+o*f,e[3]=-s*f+l*o,e[4]=l*u+f*a,e[5]=l*a-f*u,e},a.scale=function(e,t,n){var r=n[0],i=n[1];return e[0]=t[0]*r,e[1]=t[1]*i,e[2]=t[2]*r,e[3]=t[3]*i,e[4]=t[4]*r,e[5]=t[5]*i,e},a.translate=function(e,t,n){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4]+n[0],e[5]=t[5]+n[1],e},a.str=function(e){return"mat2d("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+")"},typeof e!="undefined"&&(e.mat2d=a);var f={};f.create=function(){var e=new n(9);return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=1,e[5]=0,e[6]=0,e[7]=0,e[8]=1,e},f.fromMat4=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[4],e[4]=t[5],e[5]=t[6],e[6]=t[8],e[7]=t[9],e[8]=t[10],e},f.clone=function(e){var t=new n(9);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t},f.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e},f.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=1,e[5]=0,e[6]=0,e[7]=0,e[8]=1,e},f.transpose=function(e,t){if(e===t){var n=t[1],r=t[2],i=t[5];e[1]=t[3],e[2]=t[6],e[3]=n,e[5]=t[7],e[6]=r,e[7]=i}else e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8];return e},f.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8],c=l*o-u*f,h=-l*s+u*a,p=f*s-o*a,d=n*c+r*h+i*p;return d?(d=1/d,e[0]=c*d,e[1]=(-l*r+i*f)*d,e[2]=(u*r-i*o)*d,e[3]=h*d,e[4]=(l*n-i*a)*d,e[5]=(-u*n+i*s)*d,e[6]=p*d,e[7]=(-f*n+r*a)*d,e[8]=(o*n-r*s)*d,e):null},f.adjoint=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8];return e[0]=o*l-u*f,e[1]=i*f-r*l,e[2]=r*u-i*o,e[3]=u*a-s*l,e[4]=n*l-i*a,e[5]=i*s-n*u,e[6]=s*f-o*a,e[7]=r*a-n*f,e[8]=n*o-r*s,e},f.determinant=function(e){var t=e[0],n=e[1],r=e[2],i=e[3],s=e[4],o=e[5],u=e[6],a=e[7],f=e[8];return t*(f*s-o*a)+n*(-f*i+o*u)+r*(a*i-s*u)},f.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=n[0],p=n[1],d=n[2],v=n[3],m=n[4],g=n[5],y=n[6],b=n[7],w=n[8];return e[0]=h*r+p*o+d*f,e[1]=h*i+p*u+d*l,e[2]=h*s+p*a+d*c,e[3]=v*r+m*o+g*f,e[4]=v*i+m*u+g*l,e[5]=v*s+m*a+g*c,e[6]=y*r+b*o+w*f,e[7]=y*i+b*u+w*l,e[8]=y*s+b*a+w*c,e},f.mul=f.multiply,f.translate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=n[0],p=n[1];return e[0]=r,e[1]=i,e[2]=s,e[3]=o,e[4]=u,e[5]=a,e[6]=h*r+p*o+f,e[7]=h*i+p*u+l,e[8]=h*s+p*a+c,e},f.rotate=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=Math.sin(n),p=Math.cos(n);return e[0]=p*r+h*o,e[1]=p*i+h*u,e[2]=p*s+h*a,e[3]=p*o-h*r,e[4]=p*u-h*i,e[5]=p*a-h*s,e[6]=f,e[7]=l,e[8]=c,e},f.scale=function(e,t,n){var r=n[0],i=n[2];return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=i*t[3],e[4]=i*t[4],e[5]=i*t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e},f.fromMat2d=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=0,e[3]=t[2],e[4]=t[3],e[5]=0,e[6]=t[4],e[7]=t[5],e[8]=1,e},f.fromQuat=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n+n,u=r+r,a=i+i,f=n*o,l=n*u,c=n*a,h=r*u,p=r*a,d=i*a,v=s*o,m=s*u,g=s*a;return e[0]=1-(h+d),e[1]=l+g,e[2]=c-m,e[3]=l-g,e[4]=1-(f+d),e[5]=p+v,e[6]=c+m,e[7]=p-v,e[8]=1-(f+h),e},f.str=function(e){return"mat3("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+", "+e[6]+", "+e[7]+", "+e[8]+")"},typeof e!="undefined"&&(e.mat3=f);var l={};l.create=function(){var e=new n(16);return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},l.clone=function(e){var t=new n(16);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t[9]=e[9],t[10]=e[10],t[11]=e[11],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t},l.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e},l.identity=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},l.transpose=function(e,t){if(e===t){var n=t[1],r=t[2],i=t[3],s=t[6],o=t[7],u=t[11];e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=n,e[6]=t[9],e[7]=t[13],e[8]=r,e[9]=s,e[11]=t[14],e[12]=i,e[13]=o,e[14]=u}else e[0]=t[0],e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=t[1],e[5]=t[5],e[6]=t[9],e[7]=t[13],e[8]=t[2],e[9]=t[6],e[10]=t[10],e[11]=t[14],e[12]=t[3],e[13]=t[7],e[14]=t[11],e[15]=t[15];return e},l.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8],c=t[9],h=t[10],p=t[11],d=t[12],v=t[13],m=t[14],g=t[15],y=n*u-r*o,b=n*a-i*o,w=n*f-s*o,E=r*a-i*u,S=r*f-s*u,x=i*f-s*a,T=l*v-c*d,N=l*m-h*d,C=l*g-p*d,k=c*m-h*v,L=c*g-p*v,A=h*g-p*m,O=y*A-b*L+w*k+E*C-S*N+x*T;return O?(O=1/O,e[0]=(u*A-a*L+f*k)*O,e[1]=(i*L-r*A-s*k)*O,e[2]=(v*x-m*S+g*E)*O,e[3]=(h*S-c*x-p*E)*O,e[4]=(a*C-o*A-f*N)*O,e[5]=(n*A-i*C+s*N)*O,e[6]=(m*w-d*x-g*b)*O,e[7]=(l*x-h*w+p*b)*O,e[8]=(o*L-u*C+f*T)*O,e[9]=(r*C-n*L-s*T)*O,e[10]=(d*S-v*w+g*y)*O,e[11]=(c*w-l*S-p*y)*O,e[12]=(u*N-o*k-a*T)*O,e[13]=(n*k-r*N+i*T)*O,e[14]=(v*b-d*E-m*y)*O,e[15]=(l*E-c*b+h*y)*O,e):null},l.adjoint=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=t[4],u=t[5],a=t[6],f=t[7],l=t[8],c=t[9],h=t[10],p=t[11],d=t[12],v=t[13],m=t[14],g=t[15];return e[0]=u*(h*g-p*m)-c*(a*g-f*m)+v*(a*p-f*h),e[1]=-(r*(h*g-p*m)-c*(i*g-s*m)+v*(i*p-s*h)),e[2]=r*(a*g-f*m)-u*(i*g-s*m)+v*(i*f-s*a),e[3]=-(r*(a*p-f*h)-u*(i*p-s*h)+c*(i*f-s*a)),e[4]=-(o*(h*g-p*m)-l*(a*g-f*m)+d*(a*p-f*h)),e[5]=n*(h*g-p*m)-l*(i*g-s*m)+d*(i*p-s*h),e[6]=-(n*(a*g-f*m)-o*(i*g-s*m)+d*(i*f-s*a)),e[7]=n*(a*p-f*h)-o*(i*p-s*h)+l*(i*f-s*a),e[8]=o*(c*g-p*v)-l*(u*g-f*v)+d*(u*p-f*c),e[9]=-(n*(c*g-p*v)-l*(r*g-s*v)+d*(r*p-s*c)),e[10]=n*(u*g-f*v)-o*(r*g-s*v)+d*(r*f-s*u),e[11]=-(n*(u*p-f*c)-o*(r*p-s*c)+l*(r*f-s*u)),e[12]=-(o*(c*m-h*v)-l*(u*m-a*v)+d*(u*h-a*c)),e[13]=n*(c*m-h*v)-l*(r*m-i*v)+d*(r*h-i*c),e[14]=-(n*(u*m-a*v)-o*(r*m-i*v)+d*(r*a-i*u)),e[15]=n*(u*h-a*c)-o*(r*h-i*c)+l*(r*a-i*u),e},l.determinant=function(e){var t=e[0],n=e[1],r=e[2],i=e[3],s=e[4],o=e[5],u=e[6],a=e[7],f=e[8],l=e[9],c=e[10],h=e[11],p=e[12],d=e[13],v=e[14],m=e[15],g=t*o-n*s,y=t*u-r*s,b=t*a-i*s,w=n*u-r*o,E=n*a-i*o,S=r*a-i*u,x=f*d-l*p,T=f*v-c*p,N=f*m-h*p,C=l*v-c*d,k=l*m-h*d,L=c*m-h*v;return g*L-y*k+b*C+w*N-E*T+S*x},l.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=t[4],a=t[5],f=t[6],l=t[7],c=t[8],h=t[9],p=t[10],d=t[11],v=t[12],m=t[13],g=t[14],y=t[15],b=n[0],w=n[1],E=n[2],S=n[3];return e[0]=b*r+w*u+E*c+S*v,e[1]=b*i+w*a+E*h+S*m,e[2]=b*s+w*f+E*p+S*g,e[3]=b*o+w*l+E*d+S*y,b=n[4],w=n[5],E=n[6],S=n[7],e[4]=b*r+w*u+E*c+S*v,e[5]=b*i+w*a+E*h+S*m,e[6]=b*s+w*f+E*p+S*g,e[7]=b*o+w*l+E*d+S*y,b=n[8],w=n[9],E=n[10],S=n[11],e[8]=b*r+w*u+E*c+S*v,e[9]=b*i+w*a+E*h+S*m,e[10]=b*s+w*f+E*p+S*g,e[11]=b*o+w*l+E*d+S*y,b=n[12],w=n[13],E=n[14],S=n[15],e[12]=b*r+w*u+E*c+S*v,e[13]=b*i+w*a+E*h+S*m,e[14]=b*s+w*f+E*p+S*g,e[15]=b*o+w*l+E*d+S*y,e},l.mul=l.multiply,l.translate=function(e,t,n){var r=n[0],i=n[1],s=n[2],o,u,a,f,l,c,h,p,d,v,m,g;return t===e?(e[12]=t[0]*r+t[4]*i+t[8]*s+t[12],e[13]=t[1]*r+t[5]*i+t[9]*s+t[13],e[14]=t[2]*r+t[6]*i+t[10]*s+t[14],e[15]=t[3]*r+t[7]*i+t[11]*s+t[15]):(o=t[0],u=t[1],a=t[2],f=t[3],l=t[4],c=t[5],h=t[6],p=t[7],d=t[8],v=t[9],m=t[10],g=t[11],e[0]=o,e[1]=u,e[2]=a,e[3]=f,e[4]=l,e[5]=c,e[6]=h,e[7]=p,e[8]=d,e[9]=v,e[10]=m,e[11]=g,e[12]=o*r+l*i+d*s+t[12],e[13]=u*r+c*i+v*s+t[13],e[14]=a*r+h*i+m*s+t[14],e[15]=f*r+p*i+g*s+t[15]),e},l.scale=function(e,t,n){var r=n[0],i=n[1],s=n[2];return e[0]=t[0]*r,e[1]=t[1]*r,e[2]=t[2]*r,e[3]=t[3]*r,e[4]=t[4]*i,e[5]=t[5]*i,e[6]=t[6]*i,e[7]=t[7]*i,e[8]=t[8]*s,e[9]=t[9]*s,e[10]=t[10]*s,e[11]=t[11]*s,e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e},l.rotate=function(e,n,r,i){var s=i[0],o=i[1],u=i[2],a=Math.sqrt(s*s+o*o+u*u),f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_;return Math.abs(a)<t?null:(a=1/a,s*=a,o*=a,u*=a,f=Math.sin(r),l=Math.cos(r),c=1-l,h=n[0],p=n[1],d=n[2],v=n[3],m=n[4],g=n[5],y=n[6],b=n[7],w=n[8],E=n[9],S=n[10],x=n[11],T=s*s*c+l,N=o*s*c+u*f,C=u*s*c-o*f,k=s*o*c-u*f,L=o*o*c+l,A=u*o*c+s*f,O=s*u*c+o*f,M=o*u*c-s*f,_=u*u*c+l,e[0]=h*T+m*N+w*C,e[1]=p*T+g*N+E*C,e[2]=d*T+y*N+S*C,e[3]=v*T+b*N+x*C,e[4]=h*k+m*L+w*A,e[5]=p*k+g*L+E*A,e[6]=d*k+y*L+S*A,e[7]=v*k+b*L+x*A,e[8]=h*O+m*M+w*_,e[9]=p*O+g*M+E*_,e[10]=d*O+y*M+S*_,e[11]=v*O+b*M+x*_,n!==e&&(e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15]),e)},l.rotateX=function(e,t,n){var r=Math.sin(n),i=Math.cos(n),s=t[4],o=t[5],u=t[6],a=t[7],f=t[8],l=t[9],c=t[10],h=t[11];return t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[4]=s*i+f*r,e[5]=o*i+l*r,e[6]=u*i+c*r,e[7]=a*i+h*r,e[8]=f*i-s*r,e[9]=l*i-o*r,e[10]=c*i-u*r,e[11]=h*i-a*r,e},l.rotateY=function(e,t,n){var r=Math.sin(n),i=Math.cos(n),s=t[0],o=t[1],u=t[2],a=t[3],f=t[8],l=t[9],c=t[10],h=t[11];return t!==e&&(e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=s*i-f*r,e[1]=o*i-l*r,e[2]=u*i-c*r,e[3]=a*i-h*r,e[8]=s*r+f*i,e[9]=o*r+l*i,e[10]=u*r+c*i,e[11]=a*r+h*i,e},l.rotateZ=function(e,t,n){var r=Math.sin(n),i=Math.cos(n),s=t[0],o=t[1],u=t[2],a=t[3],f=t[4],l=t[5],c=t[6],h=t[7];return t!==e&&(e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=s*i+f*r,e[1]=o*i+l*r,e[2]=u*i+c*r,e[3]=a*i+h*r,e[4]=f*i-s*r,e[5]=l*i-o*r,e[6]=c*i-u*r,e[7]=h*i-a*r,e},l.fromRotationTranslation=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=r+r,a=i+i,f=s+s,l=r*u,c=r*a,h=r*f,p=i*a,d=i*f,v=s*f,m=o*u,g=o*a,y=o*f;return e[0]=1-(p+v),e[1]=c+y,e[2]=h-g,e[3]=0,e[4]=c-y,e[5]=1-(l+v),e[6]=d+m,e[7]=0,e[8]=h+g,e[9]=d-m,e[10]=1-(l+p),e[11]=0,e[12]=n[0],e[13]=n[1],e[14]=n[2],e[15]=1,e},l.fromQuat=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n+n,u=r+r,a=i+i,f=n*o,l=n*u,c=n*a,h=r*u,p=r*a,d=i*a,v=s*o,m=s*u,g=s*a;return e[0]=1-(h+d),e[1]=l+g,e[2]=c-m,e[3]=0,e[4]=l-g,e[5]=1-(f+d),e[6]=p+v,e[7]=0,e[8]=c+m,e[9]=p-v,e[10]=1-(f+h),e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},l.frustum=function(e,t,n,r,i,s,o){var u=1/(n-t),a=1/(i-r),f=1/(s-o);return e[0]=s*2*u,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=s*2*a,e[6]=0,e[7]=0,e[8]=(n+t)*u,e[9]=(i+r)*a,e[10]=(o+s)*f,e[11]=-1,e[12]=0,e[13]=0,e[14]=o*s*2*f,e[15]=0,e},l.perspective=function(e,t,n,r,i){var s=1/Math.tan(t/2),o=1/(r-i);return e[0]=s/n,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=s,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=(i+r)*o,e[11]=-1,e[12]=0,e[13]=0,e[14]=2*i*r*o,e[15]=0,e},l.ortho=function(e,t,n,r,i,s,o){var u=1/(t-n),a=1/(r-i),f=1/(s-o);return e[0]=-2*u,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=-2*a,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=2*f,e[11]=0,e[12]=(t+n)*u,e[13]=(i+r)*a,e[14]=(o+s)*f,e[15]=1,e},l.lookAt=function(e,n,r,i){var s,o,u,a,f,c,h,p,d,v,m=n[0],g=n[1],y=n[2],b=i[0],w=i[1],E=i[2],S=r[0],x=r[1],T=r[2];return Math.abs(m-S)<t&&Math.abs(g-x)<t&&Math.abs(y-T)<t?l.identity(e):(h=m-S,p=g-x,d=y-T,v=1/Math.sqrt(h*h+p*p+d*d),h*=v,p*=v,d*=v,s=w*d-E*p,o=E*h-b*d,u=b*p-w*h,v=Math.sqrt(s*s+o*o+u*u),v?(v=1/v,s*=v,o*=v,u*=v):(s=0,o=0,u=0),a=p*u-d*o,f=d*s-h*u,c=h*o-p*s,v=Math.sqrt(a*a+f*f+c*c),v?(v=1/v,a*=v,f*=v,c*=v):(a=0,f=0,c=0),e[0]=s,e[1]=a,e[2]=h,e[3]=0,e[4]=o,e[5]=f,e[6]=p,e[7]=0,e[8]=u,e[9]=c,e[10]=d,e[11]=0,e[12]=-(s*m+o*g+u*y),e[13]=-(a*m+f*g+c*y),e[14]=-(h*m+p*g+d*y),e[15]=1,e)},l.str=function(e){return"mat4("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+", "+e[6]+", "+e[7]+", "+e[8]+", "+e[9]+", "+e[10]+", "+e[11]+", "+e[12]+", "+e[13]+", "+e[14]+", "+e[15]+")"},typeof e!="undefined"&&(e.mat4=l);var c={};c.create=function(){var e=new n(4);return e[0]=0,e[1]=0,e[2]=0,e[3]=1,e},c.clone=o.clone,c.fromValues=o.fromValues,c.copy=o.copy,c.set=o.set,c.identity=function(e){return e[0]=0,e[1]=0,e[2]=0,e[3]=1,e},c.setAxisAngle=function(e,t,n){n*=.5;var r=Math.sin(n);return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=Math.cos(n),e},c.add=o.add,c.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1],f=n[2],l=n[3];return e[0]=r*l+o*u+i*f-s*a,e[1]=i*l+o*a+s*u-r*f,e[2]=s*l+o*f+r*a-i*u,e[3]=o*l-r*u-i*a-s*f,e},c.mul=c.multiply,c.scale=o.scale,c.rotateX=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+o*u,e[1]=i*a+s*u,e[2]=s*a-i*u,e[3]=o*a-r*u,e},c.rotateY=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a-s*u,e[1]=i*a+o*u,e[2]=s*a+r*u,e[3]=o*a-i*u,e},c.rotateZ=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+i*u,e[1]=i*a-r*u,e[2]=s*a+o*u,e[3]=o*a-s*u,e},c.calculateW=function(e,t){var n=t[0],r=t[1],i=t[2];return e[0]=n,e[1]=r,e[2]=i,e[3]=-Math.sqrt(Math.abs(1-n*n-r*r-i*i)),e},c.dot=o.dot,c.lerp=o.lerp,c.slerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3],a=n[0],f=n[1],l=n[2],c=n[3],h=i*a+s*f+o*l+u*c,p,d,v,m;return Math.abs(h)>=1?(e!==t&&(e[0]=i,e[1]=s,e[2]=o,e[3]=u),e):(p=Math.acos(h),d=Math.sqrt(1-h*h),Math.abs(d)<.001?(e[0]=i*.5+a*.5,e[1]=s*.5+f*.5,e[2]=o*.5+l*.5,e[3]=u*.5+c*.5,e):(v=Math.sin((1-r)*p)/d,m=Math.sin(r*p)/d,e[0]=i*v+a*m,e[1]=s*v+f*m,e[2]=o*v+l*m,e[3]=u*v+c*m,e))},c.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*n+r*r+i*i+s*s,u=o?1/o:0;return e[0]=-n*u,e[1]=-r*u,e[2]=-i*u,e[3]=s*u,e},c.conjugate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e[3]=t[3],e},c.length=o.length,c.len=c.length,c.squaredLength=o.squaredLength,c.sqrLen=c.squaredLength,c.normalize=o.normalize,c.fromMat3=function(){var e=[1,2,0];return function(t,n){var r=n[0]+n[4]+n[8],i;if(r>0)i=Math.sqrt(r+1),t[3]=.5*i,i=.5/i,t[0]=(n[7]-n[5])*i,t[1]=(n[2]-n[6])*i,t[2]=(n[3]-n[1])*i;else{var s=0;n[4]>n[0]&&(s=1),n[8]>n[s*3+s]&&(s=2);var o=e[s],u=e[o];i=Math.sqrt(n[s*3+s]-n[o*3+o]-n[u*3+u]+1),t[s]=.5*i,i=.5/i,t[3]=(n[u*3+o]-n[o*3+u])*i,t[o]=(n[o*3+s]+n[s*3+o])*i,t[u]=(n[u*3+s]+n[s*3+u])*i}return t}}(),c.str=function(e){return"quat("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.quat=c)}(e.exports)})();'use strict';tr.exportTo('tr.b',function(){function clamp(x,lo,hi){return Math.min(Math.max(x,lo),hi);}
+function lerp(percentage,lo,hi){var range=hi-lo;return lo+percentage*range;}
+function deg2rad(deg){return(Math.PI*deg)/180.0;}
+var tmp_vec2=vec2.create();var tmp_vec2b=vec2.create();var tmp_vec4=vec4.create();var tmp_mat2d=mat2d.create();vec2.createFromArray=function(arr){if(arr.length!=2)
+throw new Error('Should be length 2');var v=vec2.create();vec2.set(v,arr[0],arr[1]);return v;};vec2.createXY=function(x,y){var v=vec2.create();vec2.set(v,x,y);return v;};vec2.toString=function(a){return'['+a[0]+', '+a[1]+']';};vec2.addTwoScaledUnitVectors=function(out,u1,scale1,u2,scale2){vec2.scale(tmp_vec2,u1,scale1);vec2.scale(tmp_vec2b,u2,scale2);vec2.add(out,tmp_vec2,tmp_vec2b);};vec2.interpolatePiecewiseFunction=function(points,x){if(x<points[0][0])
+return points[0][1];for(var i=1;i<points.length;++i){if(x<points[i][0]){var percent=(x-points[i-1][0])/(points[i][0]-points[i-1][0]);return lerp(percent,points[i-1][1],points[i][1]);}}
+return points[points.length-1][1];};vec3.createXYZ=function(x,y,z){var v=vec3.create();vec3.set(v,x,y,z);return v;};vec3.toString=function(a){return'vec3('+a[0]+', '+a[1]+', '+a[2]+')';}
 mat2d.translateXY=function(out,x,y){vec2.set(tmp_vec2,x,y);mat2d.translate(out,out,tmp_vec2);}
 mat2d.scaleXY=function(out,x,y){vec2.set(tmp_vec2,x,y);mat2d.scale(out,out,tmp_vec2);}
 vec4.unitize=function(out,a){out[0]=a[0]/a[3];out[1]=a[1]/a[3];out[2]=a[2]/a[3];out[3]=1;return out;}
 vec2.copyFromVec4=function(out,a){vec4.unitize(tmp_vec4,a);vec2.copy(out,tmp_vec4);}
-return{};});'use strict';tv.exportTo('tv.b',function(){function Rect(){this.x=0;this.y=0;this.width=0;this.height=0;};Rect.fromXYWH=function(x,y,w,h){var rect=new Rect();rect.x=x;rect.y=y;rect.width=w;rect.height=h;return rect;}
+return{clamp:clamp,lerp:lerp,deg2rad:deg2rad};});'use strict';tr.exportTo('tr.b',function(){function Rect(){this.x=0;this.y=0;this.width=0;this.height=0;};Rect.fromXYWH=function(x,y,w,h){var rect=new Rect();rect.x=x;rect.y=y;rect.width=w;rect.height=h;return rect;}
 Rect.fromArray=function(ary){if(ary.length!=4)
 throw new Error('ary.length must be 4');var rect=new Rect();rect.x=ary[0];rect.y=ary[1];rect.width=ary[2];rect.height=ary[3];return rect;}
 Rect.prototype={__proto__:Object.prototype,get left(){return this.x;},get top(){return this.y;},get right(){return this.x+this.width;},get bottom(){return this.y+this.height;},toString:function(){return'Rect('+this.x+', '+this.y+', '+
-this.width+', '+this.height+')';},toArray:function(){return[this.x,this.y,this.width,this.height];},clone:function(){var rect=new Rect();rect.x=this.x;rect.y=this.y;rect.width=this.width;rect.height=this.height;return rect;},enlarge:function(pad){var rect=new Rect();this.enlargeFast(rect,pad);return rect;},enlargeFast:function(out,pad){out.x=this.x-pad;out.y=this.y-pad;out.width=this.width+2*pad;out.height=this.height+2*pad;return out;},size:function(){return{width:this.width,height:this.height};},scale:function(s){var rect=new Rect();this.scaleFast(rect,s);return rect;},scaleSize:function(s){return Rect.fromXYWH(this.x,this.y,this.width*s,this.height*s);},scaleFast:function(out,s){out.x=this.x*s;out.y=this.y*s;out.width=this.width*s;out.height=this.height*s;return out;},translate:function(v){var rect=new Rect();this.translateFast(rect,v);return rect;},translateFast:function(out,v){out.x=this.x+v[0];out.y=this.x+v[1];out.width=this.width;out.height=this.height;return out;},asUVRectInside:function(containingRect){var rect=new Rect();rect.x=(this.x-containingRect.x)/containingRect.width;rect.y=(this.y-containingRect.y)/containingRect.height;rect.width=this.width/containingRect.width;rect.height=this.height/containingRect.height;return rect;},intersects:function(that){var ok=true;ok&=this.x<that.right;ok&=this.right>that.x;ok&=this.y<that.bottom;ok&=this.bottom>that.y;return ok;},equalTo:function(rect){return rect&&(this.x===rect.x)&&(this.y===rect.y)&&(this.width===rect.width)&&(this.height===rect.height);}};return{Rect:Rect};});'use strict';tv.exportTo('tv.b',function(){function addSingletonGetter(ctor){ctor.getInstance=function(){return ctor.instance_||(ctor.instance_=new ctor());};}
+this.width+', '+this.height+')';},toArray:function(){return[this.x,this.y,this.width,this.height];},clone:function(){var rect=new Rect();rect.x=this.x;rect.y=this.y;rect.width=this.width;rect.height=this.height;return rect;},enlarge:function(pad){var rect=new Rect();this.enlargeFast(rect,pad);return rect;},enlargeFast:function(out,pad){out.x=this.x-pad;out.y=this.y-pad;out.width=this.width+2*pad;out.height=this.height+2*pad;return out;},size:function(){return{width:this.width,height:this.height};},scale:function(s){var rect=new Rect();this.scaleFast(rect,s);return rect;},scaleSize:function(s){return Rect.fromXYWH(this.x,this.y,this.width*s,this.height*s);},scaleFast:function(out,s){out.x=this.x*s;out.y=this.y*s;out.width=this.width*s;out.height=this.height*s;return out;},translate:function(v){var rect=new Rect();this.translateFast(rect,v);return rect;},translateFast:function(out,v){out.x=this.x+v[0];out.y=this.x+v[1];out.width=this.width;out.height=this.height;return out;},asUVRectInside:function(containingRect){var rect=new Rect();rect.x=(this.x-containingRect.x)/containingRect.width;rect.y=(this.y-containingRect.y)/containingRect.height;rect.width=this.width/containingRect.width;rect.height=this.height/containingRect.height;return rect;},intersects:function(that){var ok=true;ok&=this.x<that.right;ok&=this.right>that.x;ok&=this.y<that.bottom;ok&=this.bottom>that.y;return ok;},equalTo:function(rect){return rect&&(this.x===rect.x)&&(this.y===rect.y)&&(this.width===rect.width)&&(this.height===rect.height);}};return{Rect:Rect};});'use strict';tr.exportTo('tr.b',function(){function addSingletonGetter(ctor){ctor.getInstance=function(){return ctor.instance_||(ctor.instance_=new ctor());};}
 function instantiateTemplate(selector,doc){doc=doc||document;var el=doc.querySelector(selector);if(!el)
 throw new Error('Element not found');return el.createInstance();}
 function tracedFunction(fn,name,opt_this){function F(){console.time(name);try{fn.apply(opt_this,arguments);}finally{console.timeEnd(name);}}
@@ -1746,20 +1739,17 @@
 return{message:e.message,stack:e.stack?e.stack:['<unknown>']};}
 function stackTrace(){var stack=new Error().stack+'';stack=stack.split('\n');return stack.slice(2);}
 function windowRectForElement(element){var position=[element.offsetLeft,element.offsetTop];var size=[element.offsetWidth,element.offsetHeight];var node=element.offsetParent;while(node){position[0]+=node.offsetLeft;position[1]+=node.offsetTop;node=node.offsetParent;}
-return tv.b.Rect.fromXYWH(position[0],position[1],size[0],size[1]);}
-function clamp(x,lo,hi){return Math.min(Math.max(x,lo),hi);}
-function lerp(percentage,lo,hi){var range=hi-lo;return lo+percentage*range;}
-function deg2rad(deg){return(Math.PI*deg)/180.0;}
+return tr.b.Rect.fromXYWH(position[0],position[1],size[0],size[1]);}
 function scrollIntoViewIfNeeded(el){var pr=el.parentElement.getBoundingClientRect();var cr=el.getBoundingClientRect();if(cr.top<pr.top){el.scrollIntoView(true);}else if(cr.bottom>pr.bottom){el.scrollIntoView(false);}}
 function getUsingPath(path,from_dict){var parts=path.split('.');var cur=from_dict;for(var part;parts.length&&(part=parts.shift());){if(!parts.length){return cur[part];}else if(part in cur){cur=cur[part];}else{return undefined;}}
 return undefined;}
-return{addSingletonGetter:addSingletonGetter,tracedFunction:tracedFunction,normalizeException:normalizeException,instantiateTemplate:instantiateTemplate,stackTrace:stackTrace,windowRectForElement:windowRectForElement,scrollIntoViewIfNeeded:scrollIntoViewIfNeeded,clamp:clamp,lerp:lerp,deg2rad:deg2rad,getUsingPath:getUsingPath};});'use strict';tv.exportTo('tv.b',function(){function Settings(){return Settings;};document.head.addEventListener('tv-unittest-will-run',function(){Settings.setAlternativeStorageInstance(global.sessionStorage);});function SessionSettings(){return SessionSettings;}
+return{addSingletonGetter:addSingletonGetter,tracedFunction:tracedFunction,normalizeException:normalizeException,instantiateTemplate:instantiateTemplate,stackTrace:stackTrace,windowRectForElement:windowRectForElement,scrollIntoViewIfNeeded:scrollIntoViewIfNeeded,getUsingPath:getUsingPath};});'use strict';tr.exportTo('tr.b',function(){function Settings(){return Settings;};document.head.addEventListener('tr-unittest-will-run',function(){Settings.setAlternativeStorageInstance(global.sessionStorage);});function SessionSettings(){return SessionSettings;}
 function AddStaticStorageFunctionsToClass_(input_class,storage){input_class.storage_=storage;input_class.get=function(key,opt_default,opt_namespace){key=input_class.namespace_(key,opt_namespace);var rawVal=input_class.storage_.getItem(key);if(rawVal===null||rawVal===undefined)
 return opt_default;try{return JSON.parse(rawVal).value;}catch(e){input_class.storage_.removeItem(input_class.namespace_(key,opt_namespace));return opt_default;}};input_class.set=function(key,value,opt_namespace){if(value===undefined)
 throw new Error('Settings.set: value must not be undefined');var v=JSON.stringify({value:value});input_class.storage_.setItem(input_class.namespace_(key,opt_namespace),v);};input_class.keys=function(opt_namespace){var result=[];opt_namespace=opt_namespace||'';for(var i=0;i<input_class.storage_.length;i++){var key=input_class.storage_.key(i);if(input_class.isnamespaced_(key,opt_namespace))
 result.push(input_class.unnamespace_(key,opt_namespace));}
 return result;};input_class.isnamespaced_=function(key,opt_namespace){return key.indexOf(input_class.normalize_(opt_namespace))==0;};input_class.namespace_=function(key,opt_namespace){return input_class.normalize_(opt_namespace)+key;};input_class.unnamespace_=function(key,opt_namespace){return key.replace(input_class.normalize_(opt_namespace),'');};input_class.normalize_=function(opt_namespace){return input_class.NAMESPACE+(opt_namespace?opt_namespace+'.':'');};input_class.setAlternativeStorageInstance=function(instance){input_class.storage_=instance;};input_class.getAlternativeStorageInstance=function(){if(input_class.storage_===localStorage)
-return undefined;return input_class.storage_;};input_class.NAMESPACE='trace-viewer';};AddStaticStorageFunctionsToClass_(Settings,localStorage);AddStaticStorageFunctionsToClass_(SessionSettings,sessionStorage);return{Settings:Settings,SessionSettings:SessionSettings};});'use strict';tv.exportTo('tv.b.ui',function(){function createSpan(opt_dictionary){var spanEl=document.createElement('span');if(opt_dictionary){if(opt_dictionary.className)
+return undefined;return input_class.storage_;};input_class.NAMESPACE='trace-viewer';};AddStaticStorageFunctionsToClass_(Settings,localStorage);AddStaticStorageFunctionsToClass_(SessionSettings,sessionStorage);return{Settings:Settings,SessionSettings:SessionSettings};});'use strict';tr.exportTo('tr.b.ui',function(){function createSpan(opt_dictionary){var spanEl=document.createElement('span');if(opt_dictionary){if(opt_dictionary.className)
 spanEl.className=opt_dictionary.className;if(opt_dictionary.textContent)
 spanEl.textContent=opt_dictionary.textContent;if(opt_dictionary.parent)
 opt_dictionary.parent.appendChild(spanEl);if(opt_dictionary.bold)
@@ -1778,28 +1768,28 @@
 function createSelector(targetEl,targetElProperty,settingsKey,defaultValue,items,opt_namespace){var defaultValueIndex;for(var i=0;i<items.length;i++){var item=items[i];if(valuesEqual(item.value,defaultValue)){defaultValueIndex=i;break;}}
 if(defaultValueIndex===undefined)
 throw new Error('defaultValue must be in the items list');var selectorEl=document.createElement('select');selectorEl.addEventListener('change',onChange);for(var i=0;i<items.length;i++){var item=items[i];var optionEl=document.createElement('option');optionEl.textContent=item.label;optionEl.targetPropertyValue=item.value;selectorEl.appendChild(optionEl);}
-function onChange(e){var value=selectorEl.selectedOptions[0].targetPropertyValue;tv.b.Settings.set(settingsKey,value,opt_namespace);targetEl[targetElProperty]=value;}
+function onChange(e){var value=selectorEl.selectedOptions[0].targetPropertyValue;tr.b.Settings.set(settingsKey,value,opt_namespace);targetEl[targetElProperty]=value;}
 var oldSetter=targetEl.__lookupSetter__('selectedIndex');selectorEl.__defineGetter__('selectedValue',function(v){return selectorEl.children[selectorEl.selectedIndex].targetPropertyValue;});selectorEl.__defineSetter__('selectedValue',function(v){for(var i=0;i<selectorEl.children.length;i++){var value=selectorEl.children[i].targetPropertyValue;if(valuesEqual(value,v)){var changed=selectorEl.selectedIndex!=i;if(changed){selectorEl.selectedIndex=i;onChange();}
 return;}}
-throw new Error('Not a valid value');});var initialValue=tv.b.Settings.get(settingsKey,defaultValue,opt_namespace);var didSet=false;for(var i=0;i<selectorEl.children.length;i++){if(valuesEqual(selectorEl.children[i].targetPropertyValue,initialValue)){didSet=true;targetEl[targetElProperty]=initialValue;selectorEl.selectedIndex=i;break;}}
+throw new Error('Not a valid value');});var initialValue=tr.b.Settings.get(settingsKey,defaultValue,opt_namespace);var didSet=false;for(var i=0;i<selectorEl.children.length;i++){if(valuesEqual(selectorEl.children[i].targetPropertyValue,initialValue)){didSet=true;targetEl[targetElProperty]=initialValue;selectorEl.selectedIndex=i;break;}}
 if(!didSet){selectorEl.selectedIndex=defaultValueIndex;targetEl[targetElProperty]=defaultValue;}
 return selectorEl;}
 function createEditCategorySpan(optionGroupEl,targetEl){var spanEl=createSpan({className:'edit-categories'});spanEl.textContent='Edit categories';spanEl.classList.add('labeled-option');spanEl.addEventListener('click',function(){targetEl.onClickEditCategories();});return spanEl;}
 function createOptionGroup(targetEl,targetElProperty,settingsKey,defaultValue,items){function onChange(){var value=[];if(this.value.length)
-value=this.value.split(',');tv.b.Settings.set(settingsKey,value);targetEl[targetElProperty]=value;}
-var optionGroupEl=createSpan({className:'labeled-option-group'});var initialValue=tv.b.Settings.get(settingsKey,defaultValue);for(var i=0;i<items.length;++i){var item=items[i];var id='category-preset-'+item.label.replace(/ /g,'-');var radioEl=document.createElement('input');radioEl.type='radio';radioEl.setAttribute('id',id);radioEl.setAttribute('name','category-presets-group');radioEl.setAttribute('value',item.value);radioEl.addEventListener('change',onChange.bind(radioEl,targetEl,targetElProperty,settingsKey));if(valuesEqual(initialValue,item.value))
+value=this.value.split(',');tr.b.Settings.set(settingsKey,value);targetEl[targetElProperty]=value;}
+var optionGroupEl=createSpan({className:'labeled-option-group'});var initialValue=tr.b.Settings.get(settingsKey,defaultValue);for(var i=0;i<items.length;++i){var item=items[i];var id='category-preset-'+item.label.replace(/ /g,'-');var radioEl=document.createElement('input');radioEl.type='radio';radioEl.setAttribute('id',id);radioEl.setAttribute('name','category-presets-group');radioEl.setAttribute('value',item.value);radioEl.addEventListener('change',onChange.bind(radioEl,targetEl,targetElProperty,settingsKey));if(valuesEqual(initialValue,item.value))
 radioEl.checked=true;var labelEl=document.createElement('label');labelEl.textContent=item.label;labelEl.setAttribute('for',id);var spanEl=createSpan({className:'labeled-option'});spanEl.appendChild(radioEl);spanEl.appendChild(labelEl);spanEl.__defineSetter__('checked',function(opt_bool){var changed=radioEl.checked!==(!!opt_bool);if(!changed)
 return;radioEl.checked=!!opt_bool;onChange();});spanEl.__defineGetter__('checked',function(){return radioEl.checked;});optionGroupEl.appendChild(spanEl);}
 optionGroupEl.appendChild(createEditCategorySpan(optionGroupEl,targetEl));if(!initialValue.length)
 optionGroupEl.classList.add('categories-expanded');targetEl[targetElProperty]=initialValue;return optionGroupEl;}
-var nextCheckboxId=1;function createCheckBox(targetEl,targetElProperty,settingsKey,defaultValue,label){var buttonEl=document.createElement('input');buttonEl.type='checkbox';var initialValue=tv.b.Settings.get(settingsKey,defaultValue);buttonEl.checked=!!initialValue;if(targetEl)
-targetEl[targetElProperty]=initialValue;function onChange(){tv.b.Settings.set(settingsKey,buttonEl.checked);if(targetEl)
+var nextCheckboxId=1;function createCheckBox(targetEl,targetElProperty,settingsKey,defaultValue,label){var buttonEl=document.createElement('input');buttonEl.type='checkbox';var initialValue=tr.b.Settings.get(settingsKey,defaultValue);buttonEl.checked=!!initialValue;if(targetEl)
+targetEl[targetElProperty]=initialValue;function onChange(){tr.b.Settings.set(settingsKey,buttonEl.checked);if(targetEl)
 targetEl[targetElProperty]=buttonEl.checked;}
 buttonEl.addEventListener('change',onChange);var id='#checkbox-'+nextCheckboxId++;var spanEl=createSpan({className:'labeled-checkbox'});buttonEl.setAttribute('id',id);var labelEl=document.createElement('label');labelEl.textContent=label;labelEl.setAttribute('for',id);spanEl.appendChild(buttonEl);spanEl.appendChild(labelEl);spanEl.__defineSetter__('checked',function(opt_bool){var changed=buttonEl.checked!==(!!opt_bool);if(!changed)
 return;buttonEl.checked=!!opt_bool;onChange();});spanEl.__defineGetter__('checked',function(){return buttonEl.checked;});return spanEl;}
 function isElementAttachedToDocument(el){var cur=el;while(cur.parentNode)
 cur=cur.parentNode;return(cur===el.ownerDocument||cur.nodeName==='#document-fragment');}
-return{createSpan:createSpan,createDiv:createDiv,createScopedStyle:createScopedStyle,createSelector:createSelector,createOptionGroup:createOptionGroup,createCheckBox:createCheckBox,isElementAttachedToDocument:isElementAttachedToDocument};});'use strict';tv.exportTo('tv.b',function(){function EventTarget(){}
+return{createSpan:createSpan,createDiv:createDiv,createScopedStyle:createScopedStyle,createSelector:createSelector,createOptionGroup:createOptionGroup,createCheckBox:createCheckBox,isElementAttachedToDocument:isElementAttachedToDocument};});'use strict';tr.exportTo('tr.b',function(){function EventTarget(){}
 EventTarget.decorate=function(target){for(var k in EventTarget.prototype){if(k=='decorate')
 continue;var v=EventTarget.prototype[k];if(typeof v!=='function')
 continue;target[k]=v;}};EventTarget.prototype={addEventListener:function(type,handler){if(!this.listeners_)
@@ -1815,13 +1805,13 @@
 continue;var v=EventTargetHelper[k];if(typeof v!=='function')
 continue;target[k]=v;}
 target.listenerCounts_={};},addEventListener:function(type,listener,useCapture){this.__proto__.addEventListener.call(this,type,listener,useCapture);if(this.listenerCounts_[type]===undefined)
-this.listenerCounts_[type]=0;this.listenerCounts_[type]++;},removeEventListener:function(type,listener,useCapture){this.__proto__.removeEventListener.call(this,type,listener,useCapture);this.listenerCounts_[type]--;},hasEventListener:function(type){return this.listenerCounts_[type]>0;}};return{EventTarget:EventTarget,EventTargetHelper:EventTargetHelper};});'use strict';tv.exportTo('tv.b',function(){function Event(type,opt_bubbles,opt_preventable){var e=tv.doc.createEvent('Event');e.initEvent(type,!!opt_bubbles,!!opt_preventable);e.__proto__=global.Event.prototype;return e;};Event.prototype={__proto__:global.Event.prototype};function dispatchSimpleEvent(target,type,opt_bubbles,opt_cancelable){var e=new Event(type,opt_bubbles,opt_cancelable);return target.dispatchEvent(e);}
-return{Event:Event,dispatchSimpleEvent:dispatchSimpleEvent};});'use strict';tv.exportTo('tv.b',function(){function dispatchPropertyChange(target,propertyName,newValue,oldValue,opt_bubbles,opt_cancelable){var e=new tv.b.Event(propertyName+'Change',opt_bubbles,opt_cancelable);e.propertyName=propertyName;e.newValue=newValue;e.oldValue=oldValue;var error;e.throwError=function(err){error=err;};target.dispatchEvent(e);if(error)
+this.listenerCounts_[type]=0;this.listenerCounts_[type]++;},removeEventListener:function(type,listener,useCapture){this.__proto__.removeEventListener.call(this,type,listener,useCapture);this.listenerCounts_[type]--;},hasEventListener:function(type){return this.listenerCounts_[type]>0;}};return{EventTarget:EventTarget,EventTargetHelper:EventTargetHelper};});'use strict';tr.exportTo('tr.b',function(){function Event(type,opt_bubbles,opt_preventable){var e=tr.doc.createEvent('Event');e.initEvent(type,!!opt_bubbles,!!opt_preventable);e.__proto__=global.Event.prototype;return e;};Event.prototype={__proto__:global.Event.prototype};function dispatchSimpleEvent(target,type,opt_bubbles,opt_cancelable){var e=new Event(type,opt_bubbles,opt_cancelable);return target.dispatchEvent(e);}
+return{Event:Event,dispatchSimpleEvent:dispatchSimpleEvent};});'use strict';tr.exportTo('tr.b',function(){function dispatchPropertyChange(target,propertyName,newValue,oldValue,opt_bubbles,opt_cancelable){var e=new tr.b.Event(propertyName+'Change',opt_bubbles,opt_cancelable);e.propertyName=propertyName;e.newValue=newValue;e.oldValue=oldValue;var error;e.throwError=function(err){error=err;};target.dispatchEvent(e);if(error)
 throw error;}
 function setPropertyAndDispatchChange(obj,propertyName,newValue){var privateName=propertyName+'_';var oldValue=obj[propertyName];obj[privateName]=newValue;if(oldValue!==newValue)
-tv.b.dispatchPropertyChange(obj,propertyName,newValue,oldValue,true,false);}
+tr.b.dispatchPropertyChange(obj,propertyName,newValue,oldValue,true,false);}
 function getAttributeName(jsName){return jsName.replace(/([A-Z])/g,'-$1').toLowerCase();}
-function getPrivateName(name){return name+'_tv_';}
+function getPrivateName(name){return name+'_tr_';}
 var PropertyKind={JS:'js',ATTR:'attr',BOOL_ATTR:'boolAttr'};function getGetter(name,kind){switch(kind){case PropertyKind.JS:var privateName=getPrivateName(name);return function(){return this[privateName];};case PropertyKind.ATTR:var attributeName=getAttributeName(name);return function(){return this.getAttribute(attributeName);};case PropertyKind.BOOL_ATTR:var attributeName=getAttributeName(name);return function(){return this.hasAttribute(attributeName);};}}
 function getSetter(name,kind,opt_setHook,opt_bubbles,opt_cancelable){switch(kind){case PropertyKind.JS:var privateName=getPrivateName(name);return function(value){var oldValue=this[privateName];if(value!==oldValue){this[privateName]=value;if(opt_setHook)
 opt_setHook.call(this,value,oldValue);dispatchPropertyChange(this,name,value,oldValue,opt_bubbles,opt_cancelable);}};case PropertyKind.ATTR:var attributeName=getAttributeName(name);return function(value){var oldValue=this.getAttribute(attributeName);if(value!==oldValue){if(value==undefined)
@@ -1831,32 +1821,32 @@
 this.setAttribute(attributeName,name);else
 this.removeAttribute(attributeName);if(opt_setHook)
 opt_setHook.call(this,value,oldValue);dispatchPropertyChange(this,name,value,oldValue,opt_bubbles,opt_cancelable);}};}}
-function defineProperty(obj,name,opt_kind,opt_setHook,opt_bubbles,opt_cancelable){console.error("Don't use tv.b.defineProperty");if(typeof obj=='function')
+function defineProperty(obj,name,opt_kind,opt_setHook,opt_bubbles,opt_cancelable){console.error("Don't use tr.b.defineProperty");if(typeof obj=='function')
 obj=obj.prototype;var kind=opt_kind||PropertyKind.JS;if(!obj.__lookupGetter__(name))
 obj.__defineGetter__(name,getGetter(name,kind));if(!obj.__lookupSetter__(name))
 obj.__defineSetter__(name,getSetter(name,kind,opt_setHook,opt_bubbles,opt_cancelable));}
-return{PropertyKind:PropertyKind,defineProperty:defineProperty,dispatchPropertyChange:dispatchPropertyChange,setPropertyAndDispatchChange:setPropertyAndDispatchChange};});'use strict';tv.exportTo('tv.b.ui',function(){var THIS_DOC=document.currentScript.ownerDocument;var Overlay=tv.b.ui.define('overlay');Overlay.prototype={__proto__:HTMLDivElement.prototype,decorate:function(){this.classList.add('overlay');this.parentEl_=this.ownerDocument.body;this.visible_=false;this.userCanClose_=true;this.onKeyDown_=this.onKeyDown_.bind(this);this.onClick_=this.onClick_.bind(this);this.onFocusIn_=this.onFocusIn_.bind(this);this.onDocumentClick_=this.onDocumentClick_.bind(this);this.onClose_=this.onClose_.bind(this);this.addEventListener('visibleChange',tv.b.ui.Overlay.prototype.onVisibleChange_.bind(this),true);var createShadowRoot=this.createShadowRoot||this.webkitCreateShadowRoot;this.shadow_=createShadowRoot.call(this);this.shadow_.appendChild(tv.b.instantiateTemplate('#overlay-template',THIS_DOC));this.closeBtn_=this.shadow_.querySelector('close-button');this.closeBtn_.addEventListener('click',this.onClose_);this.shadow_.querySelector('overlay-frame').addEventListener('click',this.onClick_);this.observer_=new WebKitMutationObserver(this.didButtonBarMutate_.bind(this));this.observer_.observe(this.shadow_.querySelector('button-bar'),{childList:true});Object.defineProperty(this,'title',{get:function(){return this.shadow_.querySelector('title').textContent;},set:function(title){this.shadow_.querySelector('title').textContent=title;}});},set userCanClose(userCanClose){this.userCanClose_=userCanClose;this.closeBtn_.style.display=userCanClose?'block':'none';},get buttons(){return this.shadow_.querySelector('button-bar');},get visible(){return this.visible_;},set visible(newValue){if(this.visible_===newValue)
-return;tv.b.setPropertyAndDispatchChange(this,'visible',newValue);},onVisibleChange_:function(){this.visible_?this.show_():this.hide_();},show_:function(){this.parentEl_.appendChild(this);if(this.userCanClose_){this.addEventListener('keydown',this.onKeyDown_.bind(this));this.addEventListener('click',this.onDocumentClick_.bind(this));}
+return{PropertyKind:PropertyKind,defineProperty:defineProperty,dispatchPropertyChange:dispatchPropertyChange,setPropertyAndDispatchChange:setPropertyAndDispatchChange};});'use strict';tr.exportTo('tr.b.ui',function(){var THIS_DOC=document.currentScript.ownerDocument;var Overlay=tr.b.ui.define('overlay');Overlay.prototype={__proto__:HTMLDivElement.prototype,decorate:function(){this.classList.add('overlay');this.parentEl_=this.ownerDocument.body;this.visible_=false;this.userCanClose_=true;this.onKeyDown_=this.onKeyDown_.bind(this);this.onClick_=this.onClick_.bind(this);this.onFocusIn_=this.onFocusIn_.bind(this);this.onDocumentClick_=this.onDocumentClick_.bind(this);this.onClose_=this.onClose_.bind(this);this.addEventListener('visibleChange',tr.b.ui.Overlay.prototype.onVisibleChange_.bind(this),true);var createShadowRoot=this.createShadowRoot||this.webkitCreateShadowRoot;this.shadow_=createShadowRoot.call(this);this.shadow_.appendChild(tr.b.instantiateTemplate('#overlay-template',THIS_DOC));this.closeBtn_=this.shadow_.querySelector('close-button');this.closeBtn_.addEventListener('click',this.onClose_);this.shadow_.querySelector('overlay-frame').addEventListener('click',this.onClick_);this.observer_=new WebKitMutationObserver(this.didButtonBarMutate_.bind(this));this.observer_.observe(this.shadow_.querySelector('button-bar'),{childList:true});Object.defineProperty(this,'title',{get:function(){return this.shadow_.querySelector('title').textContent;},set:function(title){this.shadow_.querySelector('title').textContent=title;}});},set userCanClose(userCanClose){this.userCanClose_=userCanClose;this.closeBtn_.style.display=userCanClose?'block':'none';},get buttons(){return this.shadow_.querySelector('button-bar');},get visible(){return this.visible_;},set visible(newValue){if(this.visible_===newValue)
+return;tr.b.setPropertyAndDispatchChange(this,'visible',newValue);},onVisibleChange_:function(){this.visible_?this.show_():this.hide_();},show_:function(){this.parentEl_.appendChild(this);if(this.userCanClose_){this.addEventListener('keydown',this.onKeyDown_.bind(this));this.addEventListener('click',this.onDocumentClick_.bind(this));}
 this.parentEl_.addEventListener('focusin',this.onFocusIn_);this.tabIndex=0;var focusEl=undefined;var elList=this.querySelectorAll('button, input, list, select, a');if(elList.length>0){if(elList[0]===this.closeBtn_){if(elList.length>1)
 focusEl=elList[1];}else{focusEl=elList[0];}}
 if(focusEl===undefined)
 focusEl=this;focusEl.focus();},hide_:function(){this.parentEl_.removeChild(this);this.parentEl_.removeEventListener('focusin',this.onFocusIn_);if(this.closeBtn_)
 this.closeBtn_.removeEventListener(this.onClose_);document.removeEventListener('keydown',this.onKeyDown_);document.removeEventListener('click',this.onDocumentClick_);},onClose_:function(e){this.visible=false;if((e.type!='keydown')||(e.type==='keydown'&&e.keyCode===27))
-e.stopPropagation();e.preventDefault();tv.b.dispatchSimpleEvent(this,'closeclick');},onFocusIn_:function(e){if(e.target===this)
+e.stopPropagation();e.preventDefault();tr.b.dispatchSimpleEvent(this,'closeclick');},onFocusIn_:function(e){if(e.target===this)
 return;window.setTimeout(function(){this.focus();},0);e.preventDefault();e.stopPropagation();},didButtonBarMutate_:function(e){var hasButtons=this.buttons.children.length>0;if(hasButtons)
 this.shadow_.querySelector('button-bar').style.display=undefined;else
 this.shadow_.querySelector('button-bar').style.display='none';},onKeyDown_:function(e){if(e.keyCode===9&&e.shiftKey&&e.target===this){e.preventDefault();return;}
 if(e.keyCode!==27)
 return;this.onClose_(e);},onClick_:function(e){e.stopPropagation();},onDocumentClick_:function(e){if(!this.userCanClose_)
-return;this.onClose_(e);}};Overlay.showError=function(msg,opt_err){var o=new Overlay();o.title='Error';o.textContent=msg;if(opt_err){var e=tv.b.normalizeException(opt_err);var stackDiv=document.createElement('pre');stackDiv.textContent=e.stack;stackDiv.style.paddingLeft='8px';stackDiv.style.margin=0;o.appendChild(stackDiv);}
+return;this.onClose_(e);}};Overlay.showError=function(msg,opt_err){var o=new Overlay();o.title='Error';o.textContent=msg;if(opt_err){var e=tr.b.normalizeException(opt_err);var stackDiv=document.createElement('pre');stackDiv.textContent=e.stack;stackDiv.style.paddingLeft='8px';stackDiv.style.margin=0;o.appendChild(stackDiv);}
 var b=document.createElement('button');b.textContent='OK';b.addEventListener('click',function(){o.visible=false;});o.buttons.appendChild(b);o.visible=true;return o;}
-return{Overlay:Overlay};});'use strict';Polymer('tv-b-dropdown',{ready:function(){this.$.outer.addEventListener('click',this.onOuterClick_.bind(this));this.$.dialog.addEventListener('click',this.onDialogClick_.bind(this));this.$.dialog.addEventListener('cancel',this.onDialogCancel_.bind(this));},get iconElement(){return this.$.icon;},onOuterClick_:function(e){var or=this.$.outer.getBoundingClientRect();var inside=true;inside&=e.clientX>=or.left;inside&=e.clientX<or.right;inside&=e.clientY>=or.top;inside&=e.clientY<or.bottom;if(!inside)
+return{Overlay:Overlay};});'use strict';Polymer('tr-b-ui-dropdown',{ready:function(){this.$.outer.addEventListener('click',this.onOuterClick_.bind(this));this.$.dialog.addEventListener('click',this.onDialogClick_.bind(this));this.$.dialog.addEventListener('cancel',this.onDialogCancel_.bind(this));},get iconElement(){return this.$.icon;},onOuterClick_:function(e){var or=this.$.outer.getBoundingClientRect();var inside=true;inside&=e.clientX>=or.left;inside&=e.clientX<or.right;inside&=e.clientY>=or.top;inside&=e.clientY<or.bottom;if(!inside)
 return;e.preventDefault();if(!this.isOpen)
 this.show();else
 this.close();},show:function(){if(this.isOpen)
 return;this.$.outer.classList.add('open');var ddr=this.$.outer.getBoundingClientRect();var rW=Math.max(ddr.width,150);this.$.dialog.style.minWidth=rW+'px';this.$.dialog.showModal();var ddw=this.$.outer.getBoundingClientRect().width;var w=this.$.dialog.getBoundingClientRect().width;this.$.dialog.style.top=ddr.bottom-1+'px';this.$.dialog.style.left=ddr.left+'px';},onDialogClick_:function(e){if(!this.isOpen)
 return;var dr=this.$.dialog.getBoundingClientRect();var inside=true;inside&=e.clientX>=dr.left;inside&=e.clientX<dr.right;inside&=e.clientY>=dr.top;inside&=e.clientY<dr.bottom;if(!inside){e.preventDefault();this.close();}},onDialogCancel_:function(e){e.preventDefault();this.close();},close:function(){if(!this.isOpen)
-return;this.$.dialog.close();this.$.outer.classList.remove('open');},get isOpen(){return this.$.dialog.hasAttribute('open');}});'use strict';tv.exportTo('tv.b.ui',function(){var DragHandle=tv.b.ui.define('x-drag-handle');DragHandle.prototype={__proto__:HTMLDivElement.prototype,decorate:function(){this.lastMousePos_=0;this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.addEventListener('mousedown',this.onMouseDown_);this.target_=undefined;this.horizontal=true;this.observer_=new WebKitMutationObserver(this.didTargetMutate_.bind(this));this.targetSizesByModeKey_={};},get modeKey_(){return this.target_.className==''?'.':this.target_.className;},get target(){return this.target_;},set target(target){this.observer_.disconnect();this.target_=target;if(!this.target_)
+return;this.$.dialog.close();this.$.outer.classList.remove('open');},get isOpen(){return this.$.dialog.hasAttribute('open');}});'use strict';tr.exportTo('tr.b.ui',function(){var DragHandle=tr.b.ui.define('x-drag-handle');DragHandle.prototype={__proto__:HTMLDivElement.prototype,decorate:function(){this.lastMousePos_=0;this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.addEventListener('mousedown',this.onMouseDown_);this.target_=undefined;this.horizontal=true;this.observer_=new WebKitMutationObserver(this.didTargetMutate_.bind(this));this.targetSizesByModeKey_={};},get modeKey_(){return this.target_.className==''?'.':this.target_.className;},get target(){return this.target_;},set target(target){this.observer_.disconnect();this.target_=target;if(!this.target_)
 return;this.observer_.observe(this.target_,{attributes:true,attributeFilter:['class']});},get horizontal(){return this.horizontal_;},set horizontal(h){this.horizontal_=h;if(this.horizontal_)
 this.className='horizontal-drag-handle';else
 this.className='vertical-drag-handle';},get vertical(){return!this.horizontal_;},set vertical(v){this.horizontal=!v;},forceMutationObserverFlush_:function(){var records=this.observer_.takeRecords();if(records.length)
@@ -1864,7 +1854,7 @@
 this.target_.style[this.targetStyleKey_]='';},get targetStyleKey_(){return this.horizontal_?'height':'width';},getTargetSize_:function(){var targetStyleKey=this.targetStyleKey_;if(!this.target_.style[targetStyleKey]){this.target_.style[targetStyleKey]=window.getComputedStyle(this.target_)[targetStyleKey];}
 var size=parseInt(this.target_.style[targetStyleKey]);this.targetSizesByModeKey_[this.modeKey_]=size;return size;},setTargetSize_:function(s){this.target_.style[this.targetStyleKey_]=s+'px';this.targetSizesByModeKey_[this.modeKey_]=s;},applyDelta_:function(delta){var curSize=this.getTargetSize_();var newSize;if(this.target_===this.nextElementSibling){newSize=curSize+delta;}else{newSize=curSize-delta;}
 this.setTargetSize_(newSize);},onMouseMove_:function(e){var curMousePos=this.horizontal_?e.clientY:e.clientX;var delta=this.lastMousePos_-curMousePos;this.applyDelta_(delta);this.lastMousePos_=curMousePos;e.preventDefault();return true;},onMouseDown_:function(e){if(!this.target_)
-return;this.forceMutationObserverFlush_();this.lastMousePos_=this.horizontal_?e.clientY:e.clientX;document.addEventListener('mousemove',this.onMouseMove_);document.addEventListener('mouseup',this.onMouseUp_);e.preventDefault();return true;},onMouseUp_:function(e){document.removeEventListener('mousemove',this.onMouseMove_);document.removeEventListener('mouseup',this.onMouseUp_);e.preventDefault();}};return{DragHandle:DragHandle};});'use strict';tv.exportTo('tv.b',function(){Object.observe(Polymer.elements,clearPolymerElementCaches);var elementsByName=undefined;var elementsThatExtend=undefined;var elementSubclasses=undefined;function clearPolymerElementCaches(){elementsByName={};elementsThatExtend=undefined;elementSubclasses={};}
+return;this.forceMutationObserverFlush_();this.lastMousePos_=this.horizontal_?e.clientY:e.clientX;document.addEventListener('mousemove',this.onMouseMove_);document.addEventListener('mouseup',this.onMouseUp_);e.preventDefault();return true;},onMouseUp_:function(e){document.removeEventListener('mousemove',this.onMouseMove_);document.removeEventListener('mouseup',this.onMouseUp_);e.preventDefault();}};return{DragHandle:DragHandle};});'use strict';tr.exportTo('tr.b',function(){Object.observe(Polymer.elements,clearPolymerElementCaches);var elementsByName=undefined;var elementsThatExtend=undefined;var elementSubclasses=undefined;function clearPolymerElementCaches(){elementsByName={};elementsThatExtend=undefined;elementSubclasses={};}
 function buildElementMapsIfNeeded(){if(elementsThatExtend!==undefined&&elementsByName!==undefined)
 return;elementsByName={};elementsThatExtend={};Polymer.elements.forEach(function(element){if(elementsByName[element.name])
 throw new Error('Something is strange: dupe polymer element names');elementsByName[element.name]=element;if(element.extends){if(elementsThatExtend[element.extends]===undefined)
@@ -1908,7 +1898,7 @@
 this.processRemovedChild_(mutation.removedNodes[i]);for(var i=0;i<mutation.addedNodes.length;i++)
 this.processAddedChild_(mutation.addedNodes[i]);},this);},tabButtonSelectHandler_:function(event,detail,sender){this.changeSelectedTabById_(sender.getAttribute('button-id'));},changeSelectedTabById_:function(id){var newTab=id!==undefined?this.tabs_[id]:undefined;var changed=this.selectedTab_!==newTab;this.saveCurrentTabScrollPosition_();this.clearSelectedTab_();if(id!==undefined){this.setSelectedTabById_(id);this.restoreCurrentTabScrollPosition_();}
 if(changed)
-this.fire('selected-tab-change');},setSelectedTabById_:function(id){this.selectedTab_=this.tabs_[id];this.selectedTab_.observers.forAttributeSelected.disconnect();this.selectedTab_.content.setAttribute('selected','selected');this.selectedTab_.observers.forAttributeSelected.observe(this.selectedTab_.content,{attributeFilter:['selected']});},saveCurrentTabScrollPosition_:function(){if(this.selectedTab_){this.selectedTab_.savedScrollTop=this.$['content-container'].scrollTop;this.selectedTab_.savedScrollLeft=this.$['content-container'].scrollLeft;}},restoreCurrentTabScrollPosition_:function(){if(this.selectedTab_){this.$['content-container'].scrollTop=this.selectedTab_.savedScrollTop;this.$['content-container'].scrollLeft=this.selectedTab_.savedScrollLeft;}},clearSelectedTab_:function(){if(this.selectedTab_){this.selectedTab_.observers.forAttributeSelected.disconnect();this.selectedTab_.content.removeAttribute('selected');this.selectedTab_.observers.forAttributeSelected.observe(this.selectedTab_.content,{attributeFilter:['selected']});this.selectedTab_=undefined;}}});'use strict';tv.exportTo('tv.b',function(){var nextGUID=1;var GUID={allocate:function(){return nextGUID++;},getLastGuid:function(){return nextGUID-1;}};return{GUID:GUID};});'use strict';tv.exportTo('tv.b',function(){function Range(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;};Range.prototype={__proto__:Object.prototype,reset:function(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;},get isEmpty(){return this.isEmpty_;},addRange:function(range){if(range.isEmpty)
+this.fire('selected-tab-change');},setSelectedTabById_:function(id){this.selectedTab_=this.tabs_[id];this.selectedTab_.observers.forAttributeSelected.disconnect();this.selectedTab_.content.setAttribute('selected','selected');this.selectedTab_.observers.forAttributeSelected.observe(this.selectedTab_.content,{attributeFilter:['selected']});},saveCurrentTabScrollPosition_:function(){if(this.selectedTab_){this.selectedTab_.savedScrollTop=this.$['content-container'].scrollTop;this.selectedTab_.savedScrollLeft=this.$['content-container'].scrollLeft;}},restoreCurrentTabScrollPosition_:function(){if(this.selectedTab_){this.$['content-container'].scrollTop=this.selectedTab_.savedScrollTop;this.$['content-container'].scrollLeft=this.selectedTab_.savedScrollLeft;}},clearSelectedTab_:function(){if(this.selectedTab_){this.selectedTab_.observers.forAttributeSelected.disconnect();this.selectedTab_.content.removeAttribute('selected');this.selectedTab_.observers.forAttributeSelected.observe(this.selectedTab_.content,{attributeFilter:['selected']});this.selectedTab_=undefined;}}});'use strict';tr.exportTo('tr.b',function(){var nextGUID=1;var GUID={allocate:function(){return nextGUID++;},getLastGuid:function(){return nextGUID-1;}};return{GUID:GUID};});'use strict';tr.exportTo('tr.b',function(){function Range(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;};Range.prototype={__proto__:Object.prototype,reset:function(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;},get isEmpty(){return this.isEmpty_;},addRange:function(range){if(range.isEmpty)
 return;this.addValue(range.min);this.addValue(range.max);},addValue:function(value){if(this.isEmpty_){this.max_=value;this.min_=value;this.isEmpty_=false;return;}
 this.max_=Math.max(this.max_,value);this.min_=Math.min(this.min_,value);},set min(min){this.isEmpty_=false;this.min_=min;},get min(){if(this.isEmpty_)
 return undefined;return this.min_;},get max(){if(this.isEmpty_)
@@ -1919,10 +1909,10 @@
 return false;return this.min<=range.min&&this.max>=range.max;},containsExplicitRange:function(min,max){if(this.isEmpty)
 return false;return this.min<=min&&this.max>=max;},intersectsRange:function(range){if(this.isEmpty||range.isEmpty)
 return false;return!(range.max<this.min||range.min>this.max);},intersectsExplicitRange:function(min,max){if(this.isEmpty)
-return false;return!(max<this.min||min>this.max);}};Range.compareByMinTimes=function(a,b){if(!a.isEmpty&&!b.isEmpty)
+return false;return!(max<this.min||min>this.max);}};Range.fromExplicitRange=function(min,max){var range=new Range();range.min=min;range.max=max;return range;};Range.compareByMinTimes=function(a,b){if(!a.isEmpty&&!b.isEmpty)
 return a.min_-b.min_;if(a.isEmpty&&!b.isEmpty)
 return-1;if(!a.isEmpty&&b.isEmpty)
-return 1;return 0;};return{Range:Range};});'use strict';tv.exportTo('tv.b',function(){function max(a,b){if(a===undefined)
+return 1;return 0;};return{Range:Range};});'use strict';tr.exportTo('tr.b',function(){function max(a,b){if(a===undefined)
 return b;if(b===undefined)
 return a;return Math.max(a,b);}
 function IntervalTree(beginPositionCb,endPositionCb){this.beginPositionCb_=beginPositionCb;this.endPositionCb_=endPositionCb;this.root_=undefined;this.size_=0;}
@@ -1947,13 +1937,13 @@
 if(this.rightNode_){this.rightNode_.appendIntersectionsInto_(ret,queryLow,queryHigh);}},get colour(){return this.colour_;},set colour(colour){this.colour_=colour;},get key(){return this.lowValue_;},get lowValue(){return this.lowValue_;},get highValue(){return this.data_[this.data_.length-1].high;},set leftNode(left){this.leftNode_=left;},get leftNode(){return this.leftNode_;},get hasLeftNode(){return this.leftNode_!==undefined;},set rightNode(right){this.rightNode_=right;},get rightNode(){return this.rightNode_;},get hasRightNode(){return this.rightNode_!==undefined;},set parentNode(parent){this.parentNode_=parent;},get parentNode(){return this.parentNode_;},get isRootNode(){return this.parentNode_===undefined;},set maxHighLeft(high){this.maxHighLeft_=high;},get maxHighLeft(){return this.maxHighLeft_;},set maxHighRight(high){this.maxHighRight_=high;},get maxHighRight(){return this.maxHighRight_;},get data(){return this.data_;},get isRed(){return this.colour_===Colour.RED;},merge:function(node){for(var i=0;i<node.data.length;i++)
 this.data_.push(node.data[i]);this.data_.sort(function(a,b){return a.high-b.high;});},dump:function(){var ret={};if(this.leftNode_)
 ret['left']=this.leftNode_.dump();ret['data']=this.data_.map(function(d){return[d.low,d.high];});if(this.rightNode_)
-ret['right']=this.rightNode_.dump();return ret;}};return{IntervalTree:IntervalTree};});'use strict';tv.exportTo('tv.b',function(){var recordRAFStacks=false;var pendingPreAFs=[];var pendingRAFs=[];var pendingIdleCallbacks=[];var currentRAFDispatchList=undefined;var rafScheduled=false;function scheduleRAF(){if(rafScheduled)
+ret['right']=this.rightNode_.dump();return ret;}};return{IntervalTree:IntervalTree};});'use strict';tr.exportTo('tr.b',function(){var recordRAFStacks=false;var pendingPreAFs=[];var pendingRAFs=[];var pendingIdleCallbacks=[];var currentRAFDispatchList=undefined;var rafScheduled=false;function scheduleRAF(){if(rafScheduled)
 return;rafScheduled=true;if(window.requestAnimationFrame){window.requestAnimationFrame(processRequests);}else{var delta=Date.now()-window.performance.now();window.webkitRequestAnimationFrame(function(domTimeStamp){processRequests(domTimeStamp-delta);});}}
 function onAnimationFrameError(e,opt_stack){if(opt_stack)
 console.log(opt_stack);if(e.message)
 console.error(e.message,e.stack);else
 console.error(e);}
-function runTask(task,frameBeginTime){try{task.callback.call(task.context,frameBeginTime);}catch(e){tv.b.onAnimationFrameError(e,task.stack);}}
+function runTask(task,frameBeginTime){try{task.callback.call(task.context,frameBeginTime);}catch(e){tr.b.onAnimationFrameError(e,task.stack);}}
 function processRequests(frameBeginTime){var rafCompletionDeadline=frameBeginTime+10;rafScheduled=false;var currentPreAFs=pendingPreAFs;currentRAFDispatchList=pendingRAFs;pendingPreAFs=[];pendingRAFs=[];var hasRAFTasks=currentPreAFs.length||currentRAFDispatchList.length;for(var i=0;i<currentPreAFs.length;i++)
 runTask(currentPreAFs[i],frameBeginTime);while(currentRAFDispatchList.length>0)
 runTask(currentRAFDispatchList.shift(),frameBeginTime);currentRAFDispatchList=undefined;if(!hasRAFTasks){while(pendingIdleCallbacks.length>0){runTask(pendingIdleCallbacks.shift());if(window.performance.now()>=rafCompletionDeadline)
@@ -1961,7 +1951,7 @@
 if(pendingIdleCallbacks.length>0)
 scheduleRAF();}
 function getStack_(){if(!recordRAFStacks)
-return'';var stackLines=tv.b.stackTrace();stackLines.shift();return stackLines.join('\n');}
+return'';var stackLines=tr.b.stackTrace();stackLines.shift();return stackLines.join('\n');}
 function requestPreAnimationFrame(callback,opt_this){pendingPreAFs.push({callback:callback,context:opt_this||window,stack:getStack_()});scheduleRAF();}
 function requestAnimationFrameInThisFrameIfPossible(callback,opt_this){if(!currentRAFDispatchList){requestAnimationFrame(callback,opt_this);return;}
 currentRAFDispatchList.push({callback:callback,context:opt_this||window,stack:getStack_()});return;}
@@ -1969,7 +1959,7 @@
 function requestIdleCallback(callback,opt_this){pendingIdleCallbacks.push({callback:callback,context:opt_this||window,stack:getStack_()});scheduleRAF();}
 function forcePendingRAFTasksToRun(frameBeginTime){if(!rafScheduled)
 return;processRequests(frameBeginTime);}
-return{onAnimationFrameError:onAnimationFrameError,requestPreAnimationFrame:requestPreAnimationFrame,requestAnimationFrame:requestAnimationFrame,requestAnimationFrameInThisFrameIfPossible:requestAnimationFrameInThisFrameIfPossible,requestIdleCallback:requestIdleCallback,forcePendingRAFTasksToRun:forcePendingRAFTasksToRun};});'use strict';tv.exportTo('tv.b',function(){function Task(runCb,thisArg){if(runCb!==undefined&&thisArg===undefined)
+return{onAnimationFrameError:onAnimationFrameError,requestPreAnimationFrame:requestPreAnimationFrame,requestAnimationFrame:requestAnimationFrame,requestAnimationFrameInThisFrameIfPossible:requestAnimationFrameInThisFrameIfPossible,requestIdleCallback:requestIdleCallback,forcePendingRAFTasksToRun:forcePendingRAFTasksToRun};});'use strict';tr.exportTo('tr.b',function(){function Task(runCb,thisArg){if(runCb!==undefined&&thisArg===undefined)
 throw new Error('Almost certainly, you meant to pass a thisArg.');this.runCb_=runCb;this.thisArg_=thisArg;this.afterTask_=undefined;this.subTasks_=[];}
 Task.prototype={subTask:function(cb,thisArg){if(cb instanceof Task)
 this.subTasks_.push(cb);else
@@ -1979,20 +1969,21 @@
 subTasks[i-1].afterTask_=subTasks[i];subTasks[subTasks.length-1].afterTask_=this.afterTask_;return subTasks[0];},after:function(cb,thisArg){if(this.afterTask_)
 throw new Error('Has an after task already');if(cb instanceof Task)
 this.afterTask_=cb;else
-this.afterTask_=new Task(cb,thisArg);return this.afterTask_;}};Task.RunSynchronously=function(task){var curTask=task;while(curTask)
+this.afterTask_=new Task(cb,thisArg);return this.afterTask_;},enqueue:function(cb,thisArg){var lastTask=this;while(lastTask.afterTask_)
+lastTask=lastTask.afterTask_;return lastTask.after(cb,thisArg);}};Task.RunSynchronously=function(task){var curTask=task;while(curTask)
 curTask=curTask.run();}
 Task.RunWhenIdle=function(task){return new Promise(function(resolve,reject){var curTask=task;function runAnother(){try{curTask=curTask.run();}catch(e){reject(e);console.error(e.stack);return;}
-if(curTask){tv.b.requestIdleCallback(runAnother);return;}
+if(curTask){tr.b.requestIdleCallback(runAnother);return;}
 resolve();}
-tv.b.requestIdleCallback(runAnother);});}
-return{Task:Task};});'use strict';tv.exportTo('tv.c',function(){function matchLower(value,pattern){return value.toLowerCase().indexOf(pattern)!==-1;}
+tr.b.requestIdleCallback(runAnother);});}
+return{Task:Task};});'use strict';tr.exportTo('tr.c',function(){function matchLower(value,pattern){return value.toLowerCase().indexOf(pattern)!==-1;}
 function Filter(){}
 Filter.prototype={__proto__:Object.prototype,matchCounter:function(counter){return true;},matchCpu:function(cpu){return true;},matchProcess:function(process){return true;},matchSlice:function(slice){return true;},matchThread:function(thread){return true;}};function TitleOrCategoryFilter(text){Filter.call(this);this.text_=text.toLowerCase();if(!text.length)
 throw new Error('Filter text is empty.');}
 TitleOrCategoryFilter.prototype={__proto__:Filter.prototype,matchSlice:function(slice){if(slice.title===undefined&&slice.category===undefined)
 return false;return matchLower(slice.title,this.text_)||(!!slice.category&&matchLower(slice.category,this.text_));}};function ExactTitleFilter(text){Filter.call(this);this.text_=text;if(!text.length)
 throw new Error('Filter text is empty.');}
-ExactTitleFilter.prototype={__proto__:Filter.prototype,matchSlice:function(slice){return slice.title===this.text_;}};return{Filter:Filter,TitleOrCategoryFilter:TitleOrCategoryFilter,ExactTitleFilter:ExactTitleFilter};});'use strict';tv.exportTo('tv.b',function(){function RegisteredTypeInfo(constructor,metadata){this.constructor=constructor;this.metadata=metadata;};var BASIC_REGISTRY_MODE='BASIC_REGISTRY_MODE';var TYPE_BASED_REGISTRY_MODE='TYPE_BASED_REGISTRY_MODE';var ALL_MODES={BASIC_REGISTRY_MODE:true,TYPE_BASED_REGISTRY_MODE:true};function ExtensionRegistryOptions(mode){if(mode===undefined)
+ExactTitleFilter.prototype={__proto__:Filter.prototype,matchSlice:function(slice){return slice.title===this.text_;}};return{Filter:Filter,TitleOrCategoryFilter:TitleOrCategoryFilter,ExactTitleFilter:ExactTitleFilter};});'use strict';tr.exportTo('tr.b',function(){function RegisteredTypeInfo(constructor,metadata){this.constructor=constructor;this.metadata=metadata;};var BASIC_REGISTRY_MODE='BASIC_REGISTRY_MODE';var TYPE_BASED_REGISTRY_MODE='TYPE_BASED_REGISTRY_MODE';var ALL_MODES={BASIC_REGISTRY_MODE:true,TYPE_BASED_REGISTRY_MODE:true};function ExtensionRegistryOptions(mode){if(mode===undefined)
 throw new Error('Mode is required');if(!ALL_MODES[mode])
 throw new Error('Not a mode.');this.mode_=mode;this.defaultMetadata_={};this.defaultConstructor_=undefined;this.mandatoryBaseClass_=undefined;this.defaultTypeInfo_=undefined;this.frozen_=false;}
 ExtensionRegistryOptions.prototype={freeze:function(){if(this.frozen_)
@@ -2003,7 +1994,7 @@
 return;var curProto=constructor.prototype.__proto__;var ok=false;while(curProto){if(curProto===this.mandatoryBaseClass.prototype){ok=true;break;}
 curProto=curProto.__proto__;}
 if(!ok)
-throw new Error(constructor+'must be subclass of '+registry);}};return{BASIC_REGISTRY_MODE:BASIC_REGISTRY_MODE,TYPE_BASED_REGISTRY_MODE:TYPE_BASED_REGISTRY_MODE,ExtensionRegistryOptions:ExtensionRegistryOptions,RegisteredTypeInfo:RegisteredTypeInfo};});'use strict';tv.exportTo('tv.b',function(){var RegisteredTypeInfo=tv.b.RegisteredTypeInfo;var ExtensionRegistryOptions=tv.b.ExtensionRegistryOptions;function decorateBasicExtensionRegistry(registry,extensionRegistryOptions){var savedStateStack=[];registry.registeredTypeInfos_=[];registry.register=function(constructor,opt_metadata){if(registry.findIndexOfRegisteredConstructor(constructor)!==undefined)
+throw new Error(constructor+'must be subclass of '+registry);}};return{BASIC_REGISTRY_MODE:BASIC_REGISTRY_MODE,TYPE_BASED_REGISTRY_MODE:TYPE_BASED_REGISTRY_MODE,ExtensionRegistryOptions:ExtensionRegistryOptions,RegisteredTypeInfo:RegisteredTypeInfo};});'use strict';tr.exportTo('tr.b',function(){var RegisteredTypeInfo=tr.b.RegisteredTypeInfo;var ExtensionRegistryOptions=tr.b.ExtensionRegistryOptions;function decorateBasicExtensionRegistry(registry,extensionRegistryOptions){var savedStateStack=[];registry.registeredTypeInfos_=[];registry.register=function(constructor,opt_metadata){if(registry.findIndexOfRegisteredConstructor(constructor)!==undefined)
 throw new Error('Handler already registered for '+constructor);extensionRegistryOptions.validateConstructor(constructor);var metadata={};for(var k in extensionRegistryOptions.defaultMetadata)
 metadata[k]=extensionRegistryOptions.defaultMetadata[k];if(opt_metadata){for(var k in opt_metadata)
 metadata[k]=opt_metadata[k];}
@@ -2014,9 +2005,9 @@
 return this.registeredTypeInfos_[foundIndex];return undefined;};registry.findTypeInfoMatching=function(predicate,opt_this){opt_this=opt_this?opt_this:undefined;for(var i=0;i<registry.registeredTypeInfos_.length;++i){var typeInfo=registry.registeredTypeInfos_[i];if(predicate.call(opt_this,typeInfo))
 return typeInfo;}
 return extensionRegistryOptions.defaultTypeInfo;};}
-return{_decorateBasicExtensionRegistry:decorateBasicExtensionRegistry};});'use strict';tv.exportTo('tv.b',function(){var categoryPartsFor={};function getCategoryParts(category){var parts=categoryPartsFor[category];if(parts!==undefined)
+return{_decorateBasicExtensionRegistry:decorateBasicExtensionRegistry};});'use strict';tr.exportTo('tr.b',function(){var categoryPartsFor={};function getCategoryParts(category){var parts=categoryPartsFor[category];if(parts!==undefined)
 return parts;parts=category.split(',');categoryPartsFor[category]=parts;return parts;}
-return{getCategoryParts:getCategoryParts};});'use strict';tv.exportTo('tv.b',function(){var getCategoryParts=tv.b.getCategoryParts;var RegisteredTypeInfo=tv.b.RegisteredTypeInfo;var ExtensionRegistryOptions=tv.b.ExtensionRegistryOptions;function decorateTypeBasedExtensionRegistry(registry,extensionRegistryOptions){var savedStateStack=[];registry.registeredTypeInfos_=[];registry.categoryPartToTypeInfoMap_={};registry.typeNameToTypeInfoMap_={};registry.register=function(constructor,metadata){extensionRegistryOptions.validateConstructor(constructor);var typeInfo=new RegisteredTypeInfo(constructor,metadata||extensionRegistryOptions.defaultMetadata);typeInfo.typeNames=[];typeInfo.categoryParts=[];if(metadata&&metadata.typeName)
+return{getCategoryParts:getCategoryParts};});'use strict';tr.exportTo('tr.b',function(){var getCategoryParts=tr.b.getCategoryParts;var RegisteredTypeInfo=tr.b.RegisteredTypeInfo;var ExtensionRegistryOptions=tr.b.ExtensionRegistryOptions;function decorateTypeBasedExtensionRegistry(registry,extensionRegistryOptions){var savedStateStack=[];registry.registeredTypeInfos_=[];registry.categoryPartToTypeInfoMap_={};registry.typeNameToTypeInfoMap_={};registry.register=function(constructor,metadata){extensionRegistryOptions.validateConstructor(constructor);var typeInfo=new RegisteredTypeInfo(constructor,metadata||extensionRegistryOptions.defaultMetadata);typeInfo.typeNames=[];typeInfo.categoryParts=[];if(metadata&&metadata.typeName)
 typeInfo.typeNames.push(metadata.typeName);if(metadata&&metadata.typeNames){typeInfo.typeNames.push.apply(typeInfo.typeNames,metadata.typeNames);}
 if(metadata&&metadata.categoryParts){typeInfo.categoryParts.push.apply(typeInfo.categoryParts,metadata.categoryParts);}
 if(typeInfo.typeNames.length===0&&typeInfo.categoryParts.length===0)
@@ -2028,32 +2019,35 @@
 if(registry.typeNameToTypeInfoMap_[typeName])
 return registry.typeNameToTypeInfoMap_[typeName];return extensionRegistryOptions.defaultTypeInfo;};registry.getConstructor=function(category,typeName){var typeInfo=registry.getTypeInfo(category,typeName);if(typeInfo)
 return typeInfo.constructor;return undefined;};}
-return{_decorateTypeBasedExtensionRegistry:decorateTypeBasedExtensionRegistry};});'use strict';tv.exportTo('tv.b',function(){function decorateExtensionRegistry(registry,registryOptions){if(registry.register)
-throw new Error('Already has registry');registryOptions.freeze();if(registryOptions.mode==tv.b.BASIC_REGISTRY_MODE){tv.b._decorateBasicExtensionRegistry(registry,registryOptions);}else if(registryOptions.mode==tv.b.TYPE_BASED_REGISTRY_MODE){tv.b._decorateTypeBasedExtensionRegistry(registry,registryOptions);}else{throw new Error('Unrecognized mode');}
+return{_decorateTypeBasedExtensionRegistry:decorateTypeBasedExtensionRegistry};});'use strict';tr.exportTo('tr.b',function(){function decorateExtensionRegistry(registry,registryOptions){if(registry.register)
+throw new Error('Already has registry');registryOptions.freeze();if(registryOptions.mode==tr.b.BASIC_REGISTRY_MODE){tr.b._decorateBasicExtensionRegistry(registry,registryOptions);}else if(registryOptions.mode==tr.b.TYPE_BASED_REGISTRY_MODE){tr.b._decorateTypeBasedExtensionRegistry(registry,registryOptions);}else{throw new Error('Unrecognized mode');}
 if(registry.addEventListener===undefined)
-tv.b.EventTarget.decorate(registry);}
-return{decorateExtensionRegistry:decorateExtensionRegistry};});'use strict';tv.exportTo('tv.c',function(){function Auditor(model){}
-Auditor.prototype={__proto__:Object.prototype,runAnnotate:function(){},runAudit:function(){}};var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Auditor;tv.b.decorateExtensionRegistry(Auditor,options);return{Auditor:Auditor};});'use strict';tv.exportTo('tv.c.importer',function(){function Importer(){}
-Importer.prototype={__proto__:Object.prototype,isTraceDataContainer:function(){return false;},extractSubtraces:function(){return[];},importEvents:function(){},importSampleData:function(){},finalizeImport:function(){},joinRefs:function(){}};var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Importer;tv.b.decorateExtensionRegistry(Importer,options);Importer.findImporterFor=function(eventData){var typeInfo=Importer.findTypeInfoMatching(function(ti){return ti.constructor.canImport(eventData);});if(typeInfo)
-return typeInfo.constructor;return undefined;};return{Importer:Importer};});'use strict';tv.exportTo('tv.c.importer',function(){var Importer=tv.c.importer.Importer;function EmptyImporter(events){this.importPriority=0;};EmptyImporter.canImport=function(eventData){if(eventData instanceof Array&&eventData.length==0)
+tr.b.EventTarget.decorate(registry);}
+return{decorateExtensionRegistry:decorateExtensionRegistry};});'use strict';tr.exportTo('tr.c',function(){function Auditor(model){}
+Auditor.prototype={__proto__:Object.prototype,runAnnotate:function(){},runAudit:function(){}};var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Auditor;tr.b.decorateExtensionRegistry(Auditor,options);return{Auditor:Auditor};});'use strict';tr.exportTo('tr.importer',function(){function Importer(){}
+Importer.prototype={__proto__:Object.prototype,isTraceDataContainer:function(){return false;},extractSubtraces:function(){return[];},importEvents:function(){},importSampleData:function(){},finalizeImport:function(){},joinRefs:function(){}};var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Importer;tr.b.decorateExtensionRegistry(Importer,options);Importer.findImporterFor=function(eventData){var typeInfo=Importer.findTypeInfoMatching(function(ti){return ti.constructor.canImport(eventData);});if(typeInfo)
+return typeInfo.constructor;return undefined;};return{Importer:Importer};});'use strict';tr.exportTo('tr.importer',function(){var Importer=tr.importer.Importer;function EmptyImporter(events){this.importPriority=0;};EmptyImporter.canImport=function(eventData){if(eventData instanceof Array&&eventData.length==0)
 return true;if(typeof(eventData)==='string'||eventData instanceof String){return eventData.length==0;}
-return false;};EmptyImporter.prototype={__proto__:Importer.prototype};Importer.register(EmptyImporter);return{EmptyImporter:EmptyImporter};});'use strict';tv.exportTo('tv.c.trace_model',function(){var SelectionState={NONE:0,SELECTED:1,HIGHLIGHTED:2,DIMMED:3};return{SelectionState:SelectionState};});'use strict';tv.exportTo('tv.c.trace_model',function(){var SelectionState=tv.c.trace_model.SelectionState;function SelectableItem(modelItem){this.modelItem_=modelItem;}
+return false;};EmptyImporter.prototype={__proto__:Importer.prototype};Importer.register(EmptyImporter);return{EmptyImporter:EmptyImporter};});'use strict';tr.exportTo('tr.model',function(){function EventContainer(){this.important=true;this.bounds=undefined;}
+EventContainer.prototype={get stableId(){throw new Error('Not implemented');},updateBounds:function(){throw new Error('Not implemented');},shiftTimestampsForward:function(amount){throw new Error('Not implemented');},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){throw new Error('Not implemented');},iterateAllChildEventContainers:function(callback,opt_this){throw new Error('Not implemented');},iterateAllEvents:function(callback,opt_this){this.iterateAllEventContainers(function(ec){ec.iterateAllEventsInThisContainer(function(eventType){return true;},callback,opt_this);});},iterateAllEventContainers:function(callback,opt_this){function visit(ec){callback.call(opt_this,ec);ec.iterateAllChildEventContainers(visit);}
+visit(this);}};return{EventContainer:EventContainer};});'use strict';tr.exportTo('tr.model',function(){function Device(model){if(!model)
+throw new Error('Must provide a model.');tr.model.EventContainer.call(this);this.bounds=new tr.b.Range();this.guid=tr.b.GUID.allocate();};Device.compare=function(x,y){return x.guid-y.guid;};Device.prototype={__proto__:tr.model.EventContainer.prototype,compareTo:function(that){return Device.compare(this,that);},get userFriendlyName(){return'Device';},get userFriendlyDetails(){return'Device';},get stableId(){return'Device';},getSettingsKey:function(){return'device';},get counters(){return{};},updateBounds:function(){this.bounds.reset();},shiftTimestampsForward:function(amount){},addCategoriesToDict:function(categoriesDict){},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){},iterateAllChildEventContainers:function(callback,opt_this){}};return{Device:Device};});'use strict';tr.exportTo('tr.model',function(){var SelectionState={NONE:0,SELECTED:1,HIGHLIGHTED:2,DIMMED:3};return{SelectionState:SelectionState};});'use strict';tr.exportTo('tr.model',function(){var SelectionState=tr.model.SelectionState;function SelectableItem(modelItem){this.modelItem_=modelItem;}
 SelectableItem.prototype={get modelItem(){return this.modelItem_;},get selected(){return this.selectionState===SelectionState.SELECTED;},addToSelection:function(selection){var modelItem=this.modelItem_;if(!modelItem)
 return;selection.push(modelItem);},addToTrackMap:function(eventToTrackMap,track){var modelItem=this.modelItem_;if(!modelItem)
-return;eventToTrackMap.addEvent(modelItem,track);}};return{SelectableItem:SelectableItem};});'use strict';tv.exportTo('tv.c.trace_model',function(){var SelectableItem=tv.c.trace_model.SelectableItem;var SelectionState=tv.c.trace_model.SelectionState;var categoryPartsFor={};function getCategoryParts(category){var parts=categoryPartsFor[category];if(parts!==undefined)
+return;eventToTrackMap.addEvent(modelItem,track);}};return{SelectableItem:SelectableItem};});'use strict';tr.exportTo('tr.model',function(){var SelectableItem=tr.model.SelectableItem;var SelectionState=tr.model.SelectionState;var categoryPartsFor={};function getCategoryParts(category){var parts=categoryPartsFor[category];if(parts!==undefined)
 return parts;parts=category.split(',');categoryPartsFor[category]=parts;return parts;}
-function Event(){SelectableItem.call(this,this);this.guid_=tv.b.GUID.allocate();this.selectionState=SelectionState.NONE;this.associatedAlerts=[];this.info=undefined;}
+function Event(){SelectableItem.call(this,this);this.guid_=tr.b.GUID.allocate();this.selectionState=SelectionState.NONE;this.associatedAlerts=[];this.info=undefined;}
 Event.prototype={__proto__:SelectableItem.prototype,get guid(){return this.guid_;}};function EventRegistry(){}
-var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);options.mandatoryBaseType=Event;tv.b.decorateExtensionRegistry(EventRegistry,options);EventRegistry.addEventListener('will-register',function(e){var metadata=e.typeInfo.metadata;if(metadata.name===undefined)
-throw new Error('Registered events must provide name metadata');var i=tv.b.findFirstInArray(EventRegistry.getAllRegisteredTypeInfos(),function(x){return x.metadata.name===metadata.name;});if(i!==undefined)
+var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.mandatoryBaseType=Event;tr.b.decorateExtensionRegistry(EventRegistry,options);EventRegistry.addEventListener('will-register',function(e){var metadata=e.typeInfo.metadata;if(metadata.name===undefined)
+throw new Error('Registered events must provide name metadata');var i=tr.b.findFirstInArray(EventRegistry.getAllRegisteredTypeInfos(),function(x){return x.metadata.name===metadata.name;});if(i!==undefined)
 throw new Error('Event type with that name already registered');if(metadata.pluralName===undefined)
 throw new Error('Registered events must provide pluralName metadata');if(metadata.singleViewElementName===undefined){throw new Error('Registered events must provide '+'singleViewElementName metadata');}
 if(metadata.multiViewElementName===undefined){throw new Error('Registered events must provide '+'multiViewElementName metadata');}});var eventsByTypeName=undefined;EventRegistry.getEventTypeInfoByTypeName=function(typeName){if(eventsByTypeName===undefined){eventsByTypeName={};EventRegistry.getAllRegisteredTypeInfos().forEach(function(typeInfo){eventsByTypeName[typeInfo.metadata.name]=typeInfo;});}
 return eventsByTypeName[typeName];}
 EventRegistry.addEventListener('registry-changed',function(){eventsByTypeName=undefined;});function convertCamelCaseToTitleCase(name){var result=name.replace(/[A-Z]/g,' $&');result=result.charAt(0).toUpperCase()+result.slice(1);return result;}
-EventRegistry.getUserFriendlySingularName=function(typeName){var typeInfo=EventRegistry.getEventTypeInfoByTypeName(typeName);var str=typeInfo.metadata.name;return convertCamelCaseToTitleCase(str);};EventRegistry.getUserFriendlyPluralName=function(typeName){var typeInfo=EventRegistry.getEventTypeInfoByTypeName(typeName);var str=typeInfo.metadata.pluralName;return convertCamelCaseToTitleCase(str);};return{Event:Event,EventRegistry:EventRegistry};});'use strict';tv.exportTo('tv.c.analysis',function(){function tsString(ts){return Number(tsRound(ts)).toLocaleString(undefined,{minimumFractionDigits:3})+' ms';}
-function tsRound(ts){return Math.round(ts*1000.0)/1000.0;}
-return{tsString:tsString,tsRound:tsRound};});'use strict';tv.exportTo('tv.b',function(){function findLowIndexInSortedArray(ary,mapFn,loVal){if(ary.length==0)
+EventRegistry.getUserFriendlySingularName=function(typeName){var typeInfo=EventRegistry.getEventTypeInfoByTypeName(typeName);var str=typeInfo.metadata.name;return convertCamelCaseToTitleCase(str);};EventRegistry.getUserFriendlyPluralName=function(typeName){var typeInfo=EventRegistry.getEventTypeInfoByTypeName(typeName);var str=typeInfo.metadata.pluralName;return convertCamelCaseToTitleCase(str);};return{Event:Event,EventRegistry:EventRegistry};});'use strict';tr.exportTo('tr.b.units',function(){var ms={suffix:'ms',format:function(ts){var tsRounded=Math.round(ts*1000.0)/1000.0;var n=new Number(tsRounded);return n.toLocaleString(undefined,{minimumFractionDigits:3})+' ms';}};var ns={suffix:'ns',format:function(ts){var tsRounded=Math.round(ts*1000000.0);var n=new Number(tsRounded);return n.toLocaleString(undefined,{maximumFractionDigits:0})+' ns';}};var Time={supportedUnits:{ms:ms,ns:ns},reset:function(){this.currentDisplayUnit=ms;},currentDisplayUnit_:ms,get currentDisplayUnit(){return this.currentDisplayUnit_;},set currentDisplayUnit(value){if(this.currentDisplayUnit_==value)
+return;this.currentDisplayUnit_=value;this.dispatchEvent(new Event('display-unit-changed'));}};tr.b.EventTarget.decorate(Time);return{Time:Time};});'use strict';tr.exportTo('tr.b.units',function(){function tsString(ts){return tr.b.units.Time.currentDisplayUnit.format(ts);}
+return{tsString:tsString};});'use strict';tr.exportTo('tr.b',function(){function findLowIndexInSortedArray(ary,mapFn,loVal){if(ary.length==0)
 return 1;var low=0;var high=ary.length-1;var i,comparison;var hitPos=-1;while(low<=high){i=Math.floor((low+high)/2);comparison=mapFn(ary[i])-loVal;if(comparison<0){low=i+1;continue;}else if(comparison>0){high=i-1;continue;}else{hitPos=i;high=i-1;}}
 return hitPos!=-1?hitPos:low;}
 function findIndexInSortedIntervals(ary,mapLoFn,mapWidthFn,loVal){var first=findLowIndexInSortedArray(ary,mapLoFn,loVal);if(first==0){if(loVal>=mapLoFn(ary[0])&&loVal<mapLoFn(ary[0])+mapWidthFn(ary[0],0)){return 0;}else{return-1;}}else if(first<ary.length){if(loVal>=mapLoFn(ary[first])&&loVal<mapLoFn(ary[first])+mapWidthFn(ary[first],first)){return first;}else if(loVal>=mapLoFn(ary[first-1])&&loVal<mapLoFn(ary[first-1])+
@@ -2078,35 +2072,34 @@
 return null;if(loDiff<hiDiff)
 return loInt;else
 return hiInt;}
-return{findLowIndexInSortedArray:findLowIndexInSortedArray,findIndexInSortedIntervals:findIndexInSortedIntervals,findIndexInSortedClosedIntervals:findIndexInSortedClosedIntervals,iterateOverIntersectingIntervals:iterateOverIntersectingIntervals,getIntersectingIntervals:getIntersectingIntervals,findClosestElementInSortedArray:findClosestElementInSortedArray,findClosestIntervalInSortedIntervals:findClosestIntervalInSortedIntervals};});'use strict';tv.exportTo('tv.c.trace_model',function(){function CounterSample(series,timestamp,value){tv.c.trace_model.Event.call(this);this.series_=series;this.timestamp_=timestamp;this.value_=value;}
-CounterSample.groupByTimestamp=function(samples){var samplesByTimestamp={};for(var i=0;i<samples.length;i++){var sample=samples[i];var ts=sample.timestamp;if(!samplesByTimestamp[ts])
-samplesByTimestamp[ts]=[];samplesByTimestamp[ts].push(sample);}
-var timestamps=tv.b.dictionaryKeys(samplesByTimestamp);timestamps.sort();var groups=[];for(var i=0;i<timestamps.length;i++){var ts=timestamps[i];var group=samplesByTimestamp[ts];group.sort(function(x,y){return x.series.seriesIndex-y.series.seriesIndex;});groups.push(group);}
+return{findLowIndexInSortedArray:findLowIndexInSortedArray,findIndexInSortedIntervals:findIndexInSortedIntervals,findIndexInSortedClosedIntervals:findIndexInSortedClosedIntervals,iterateOverIntersectingIntervals:iterateOverIntersectingIntervals,getIntersectingIntervals:getIntersectingIntervals,findClosestElementInSortedArray:findClosestElementInSortedArray,findClosestIntervalInSortedIntervals:findClosestIntervalInSortedIntervals};});'use strict';tr.exportTo('tr.model',function(){function CounterSample(series,timestamp,value){tr.model.Event.call(this);this.series_=series;this.timestamp_=timestamp;this.value_=value;}
+CounterSample.groupByTimestamp=function(samples){var samplesByTimestamp=tr.b.group(samples,function(sample){return sample.timestamp;});var timestamps=tr.b.dictionaryKeys(samplesByTimestamp);timestamps.sort();var groups=[];for(var i=0;i<timestamps.length;i++){var ts=timestamps[i];var group=samplesByTimestamp[ts];group.sort(function(x,y){return x.series.seriesIndex-y.series.seriesIndex;});groups.push(group);}
 return groups;}
-CounterSample.prototype={__proto__:tv.c.trace_model.Event.prototype,get series(){return this.series_;},get timestamp(){return this.timestamp_;},get value(){return this.value_;},set timestamp(timestamp){this.timestamp_=timestamp;},addBoundsToRange:function(range){range.addValue(this.timestamp);},getSampleIndex:function(){return tv.b.findLowIndexInSortedArray(this.series.timestamps,function(x){return x;},this.timestamp_);},get userFriendlyName(){return'Counter sample from '+this.series_.title+' at '+
-tv.c.analysis.tsString(this.timestamp);}};tv.c.trace_model.EventRegistry.register(CounterSample,{name:'counterSample',pluralName:'counterSamples',singleViewElementName:'tv-c-counter-sample-sub-view',multiViewElementName:'tv-c-counter-sample-sub-view'});return{CounterSample:CounterSample};});'use strict';tv.exportTo('tv.c.trace_model',function(){function EventContainer(){this.important=true;this.bounds=undefined;}
-EventContainer.prototype={get stableId(){throw new Error('Not implemented');},updateBounds:function(){throw new Error('Not implemented');},shiftTimestampsForward:function(amount){throw new Error('Not implemented');},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){throw new Error('Not implemented');},iterateAllChildEventContainers:function(callback,opt_this){throw new Error('Not implemented');},iterateAllEvents:function(callback,opt_this){this.iterateAllEventContainers(function(ec){ec.iterateAllEventsInThisContainer(function(eventType){return true;},callback,opt_this);});},iterateAllEventContainers:function(callback,opt_this){function visit(ec){callback.call(opt_this,ec);ec.iterateAllChildEventContainers(visit);}
-visit(this);}};return{EventContainer:EventContainer};});'use strict';tv.exportTo('tv.c.trace_model',function(){var CounterSample=tv.c.trace_model.CounterSample;function CounterSeries(name,color){tv.c.trace_model.EventContainer.call(this);this.guid_=tv.b.GUID.allocate();this.name_=name;this.color_=color;this.timestamps_=[];this.samples_=[];this.counter=undefined;this.seriesIndex=undefined;}
-CounterSeries.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,get length(){return this.timestamps_.length;},get name(){return this.name_;},get color(){return this.color_;},get samples(){return this.samples_;},get timestamps(){return this.timestamps_;},getSample:function(idx){return this.samples_[idx];},getTimestamp:function(idx){return this.timestamps_[idx];},addCounterSample:function(ts,val){var sample=new CounterSample(this,ts,val);this.addSample(sample);return sample;},addSample:function(sample){this.timestamps_.push(sample.timestamp);this.samples_.push(sample);},getStatistics:function(sampleIndices){var sum=0;var min=Number.MAX_VALUE;var max=-Number.MAX_VALUE;for(var i=0;i<sampleIndices.length;++i){var sample=this.getSample(sampleIndices[i]).value;sum+=sample;min=Math.min(sample,min);max=Math.max(sample,max);}
-return{min:min,max:max,avg:(sum/sampleIndices.length),start:this.getSample(sampleIndices[0]).value,end:this.getSample(sampleIndices.length-1).value};},shiftTimestampsForward:function(amount){for(var i=0;i<this.timestamps_.length;++i){this.timestamps_[i]+=amount;this.samples_[i].timestamp=this.timestamps_[i];}},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,tv.c.trace_model.CounterSample)){this.samples_.forEach(callback,opt_this);}},iterateAllChildEventContainers:function(callback,opt_this){}};return{CounterSeries:CounterSeries};});'use strict';tv.exportTo('tv.c.trace_model',function(){function Counter(parent,id,category,name){tv.c.trace_model.EventContainer.call(this);this.guid_=tv.b.GUID.allocate();this.parent=parent;this.id=id;this.category=category||'';this.name=name;this.series_=[];this.totals=[];this.bounds=new tv.b.Range();}
-Counter.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,get guid(){return this.guid_;},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){},iterateAllChildEventContainers:function(callback,opt_this){for(var i=0;i<this.series_.length;i++)
+CounterSample.prototype={__proto__:tr.model.Event.prototype,get series(){return this.series_;},get timestamp(){return this.timestamp_;},get value(){return this.value_;},set timestamp(timestamp){this.timestamp_=timestamp;},addBoundsToRange:function(range){range.addValue(this.timestamp);},getSampleIndex:function(){return tr.b.findLowIndexInSortedArray(this.series.timestamps,function(x){return x;},this.timestamp_);},get userFriendlyName(){return'Counter sample from '+this.series_.title+' at '+
+tr.b.units.tsString(this.timestamp);}};tr.model.EventRegistry.register(CounterSample,{name:'counterSample',pluralName:'counterSamples',singleViewElementName:'tr-c-a-counter-sample-sub-view',multiViewElementName:'tr-c-a-counter-sample-sub-view'});return{CounterSample:CounterSample};});'use strict';tr.exportTo('tr.model',function(){var CounterSample=tr.model.CounterSample;function CounterSeries(name,color){tr.model.EventContainer.call(this);this.guid_=tr.b.GUID.allocate();this.name_=name;this.color_=color;this.timestamps_=[];this.samples_=[];this.counter=undefined;this.seriesIndex=undefined;}
+CounterSeries.prototype={__proto__:tr.model.EventContainer.prototype,get length(){return this.timestamps_.length;},get name(){return this.name_;},get color(){return this.color_;},get samples(){return this.samples_;},get timestamps(){return this.timestamps_;},getSample:function(idx){return this.samples_[idx];},getTimestamp:function(idx){return this.timestamps_[idx];},addCounterSample:function(ts,val){var sample=new CounterSample(this,ts,val);this.addSample(sample);return sample;},addSample:function(sample){this.timestamps_.push(sample.timestamp);this.samples_.push(sample);},getStatistics:function(sampleIndices){var sum=0;var min=Number.MAX_VALUE;var max=-Number.MAX_VALUE;for(var i=0;i<sampleIndices.length;++i){var sample=this.getSample(sampleIndices[i]).value;sum+=sample;min=Math.min(sample,min);max=Math.max(sample,max);}
+return{min:min,max:max,avg:(sum/sampleIndices.length),start:this.getSample(sampleIndices[0]).value,end:this.getSample(sampleIndices.length-1).value};},shiftTimestampsForward:function(amount){for(var i=0;i<this.timestamps_.length;++i){this.timestamps_[i]+=amount;this.samples_[i].timestamp=this.timestamps_[i];}},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,tr.model.CounterSample)){this.samples_.forEach(callback,opt_this);}},iterateAllChildEventContainers:function(callback,opt_this){}};return{CounterSeries:CounterSeries};});'use strict';tr.exportTo('tr.model',function(){function Counter(parent,id,category,name){tr.model.EventContainer.call(this);this.guid_=tr.b.GUID.allocate();this.parent_=parent;this.id_=id;this.category_=category||'';this.name_=name;this.series_=[];this.totals=[];this.bounds=new tr.b.Range();}
+Counter.prototype={__proto__:tr.model.EventContainer.prototype,get guid(){return this.guid_;},get parent(){return this.parent_;},get id(){return this.id_;},get category(){return this.category_;},get name(){return this.name_;},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){},iterateAllChildEventContainers:function(callback,opt_this){for(var i=0;i<this.series_.length;i++)
 callback.call(opt_this,this.series_[i]);},set timestamps(arg){throw new Error('Bad counter API. No cookie.');},set seriesNames(arg){throw new Error('Bad counter API. No cookie.');},set seriesColors(arg){throw new Error('Bad counter API. No cookie.');},set samples(arg){throw new Error('Bad counter API. No cookie.');},addSeries:function(series){series.counter=this;series.seriesIndex=this.series_.length;this.series_.push(series);return series;},getSeries:function(idx){return this.series_[idx];},get series(){return this.series_;},get numSeries(){return this.series_.length;},get numSamples(){if(this.series_.length===0)
 return 0;return this.series_[0].length;},get timestamps(){if(this.series_.length===0)
 return[];return this.series_[0].timestamps;},getSampleStatistics:function(sampleIndices){sampleIndices.sort();var ret=[];this.series_.forEach(function(series){ret.push(series.getStatistics(sampleIndices));});return ret;},shiftTimestampsForward:function(amount){for(var i=0;i<this.series_.length;++i)
 this.series_[i].shiftTimestampsForward(amount);},updateBounds:function(){this.totals=[];this.maxTotal=0;this.bounds.reset();if(this.series_.length===0)
 return;var firstSeries=this.series_[0];var lastSeries=this.series_[this.series_.length-1];this.bounds.addValue(firstSeries.getTimestamp(0));this.bounds.addValue(lastSeries.getTimestamp(lastSeries.length-1));var numSeries=this.numSeries;this.maxTotal=-Infinity;for(var i=0;i<firstSeries.length;++i){var total=0;this.series_.forEach(function(series){total+=series.getSample(i).value;this.totals.push(total);}.bind(this));this.maxTotal=Math.max(total,this.maxTotal);}}};Counter.compare=function(x,y){var tmp=x.parent.compareTo(y);if(tmp!=0)
 return tmp;var tmp=x.name.localeCompare(y.name);if(tmp==0)
-return x.tid-y.tid;return tmp;};return{Counter:Counter};});'use strict';tv.exportTo('tv.c.trace_model',function(){function TimedEvent(start){tv.c.trace_model.Event.call(this);this.start=start;this.duration=0;this.cpuStart=undefined;this.cpuDuration=undefined;}
-TimedEvent.prototype={__proto__:tv.c.trace_model.Event.prototype,get end(){return this.start+this.duration;},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);},bounds:function(that){var this_end_micros=Math.round(this.end*1000);var that_end_micros=Math.round(that.end*1000);return this.start<=that.start&&this_end_micros>=that_end_micros;}};return{TimedEvent:TimedEvent};});'use strict';tv.exportTo('tv.c.trace_model',function(){function Slice(category,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration){tv.c.trace_model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.startStackFrame=undefined;this.endStackFrame=undefined;this.didNotFinish=false;this.inFlowEvents=[];this.outFlowEvents=[];this.subSlices=[];this.selfTime=undefined;this.cpuSelfTime=undefined;this.important=false;if(opt_duration!==undefined)
+return x.tid-y.tid;return tmp;};return{Counter:Counter};});'use strict';tr.exportTo('tr.model',function(){function TimedEvent(start){tr.model.Event.call(this);this.start=start;this.duration=0;this.cpuStart=undefined;this.cpuDuration=undefined;}
+TimedEvent.prototype={__proto__:tr.model.Event.prototype,get end(){return this.start+this.duration;},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);},bounds:function(that){var this_end_micros=Math.round(this.end*1000);var that_end_micros=Math.round(that.end*1000);return this.start<=that.start&&this_end_micros>=that_end_micros;}};return{TimedEvent:TimedEvent};});'use strict';tr.exportTo('tr.model',function(){function Slice(category,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.startStackFrame=undefined;this.endStackFrame=undefined;this.didNotFinish=false;this.inFlowEvents=[];this.outFlowEvents=[];this.subSlices=[];this.selfTime=undefined;this.cpuSelfTime=undefined;this.important=false;this.parentContainer=undefined;if(opt_duration!==undefined)
 this.duration=opt_duration;if(opt_cpuStart!==undefined)
 this.cpuStart=opt_cpuStart;if(opt_cpuDuration!==undefined)
 this.cpuDuration=opt_cpuDuration;}
-Slice.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get userFriendlyName(){return'Slice '+this.title+' at '+
-tv.c.analysis.tsString(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices)
+Slice.prototype={__proto__:tr.model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get userFriendlyName(){return'Slice '+this.title+' at '+
+tr.b.units.tsString(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices)
 return undefined;for(var i=0;i<this.subSlices.length;i++){if(this.subSlices[i].title==targetTitle)
 return this.subSlices[i];var slice=this.subSlices[i].findDescendentSlice(targetTitle);if(slice)return slice;}
-return undefined;},iterateAllDescendents:function(callback,opt_this){this.subSlices.forEach(callback,opt_this);this.subSlices.forEach(function(subSlice){subSlice.iterateAllDescendents(callback,opt_this);},opt_this);}};return{Slice:Slice};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Slice=tv.c.trace_model.Slice;var SCHEDULING_STATE={DEBUG:'Debug',EXIT_DEAD:'Exit Dead',RUNNABLE:'Runnable',RUNNING:'Running',SLEEPING:'Sleeping',STOPPED:'Stopped',TASK_DEAD:'Task Dead',UNINTR_SLEEP:'Uninterruptible Sleep',UNINTR_SLEEP_WAKE_KILL:'Uninterruptible Sleep | WakeKill',UNINTR_SLEEP_WAKING:'Uninterruptible Sleep | Waking',UNKNOWN:'UNKNOWN',WAKE_KILL:'Wakekill',WAKING:'Waking',ZOMBIE:'Zombie'};function ThreadTimeSlice(thread,schedulingState,cat,start,args,opt_duration){Slice.call(this,cat,schedulingState,this.getColorForState_(schedulingState),start,args,opt_duration);this.thread=thread;this.schedulingState=schedulingState;this.cpuOnWhichThreadWasRunning=undefined;}
-ThreadTimeSlice.prototype={__proto__:Slice.prototype,getColorForState_:function(state){var getColorIdForReservedName=tv.b.ui.getColorIdForReservedName;switch(state){case SCHEDULING_STATE.RUNNABLE:return getColorIdForReservedName('thread_state_runnable');case SCHEDULING_STATE.RUNNING:return getColorIdForReservedName('thread_state_running');case SCHEDULING_STATE.SLEEPING:return getColorIdForReservedName('thread_state_sleeping');case SCHEDULING_STATE.DEBUG:case SCHEDULING_STATE.EXIT_DEAD:case SCHEDULING_STATE.STOPPED:case SCHEDULING_STATE.TASK_DEAD:case SCHEDULING_STATE.UNINTR_SLEEP:case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL:case SCHEDULING_STATE.UNINTR_SLEEP_WAKING:case SCHEDULING_STATE.UNKNOWN:case SCHEDULING_STATE.WAKE_KILL:case SCHEDULING_STATE.WAKING:case SCHEDULING_STATE.ZOMBIE:return getColorIdForReservedName('thread_state_iowait');default:return getColorIdForReservedName('thread_state_unknown');}},get analysisTypeName(){return'tv.c.analysis.ThreadTimeSlice';},getAssociatedCpuSlice:function(){if(!this.cpuOnWhichThreadWasRunning)
+return undefined;},get mostTopLevelSlice(){var curSlice=this;while(curSlice.parentSlice)
+curSlice=curSlice.parentSlice;return curSlice;},iterateAllSubsequentSlices:function(callback,opt_this){var parentStack=[];var started=false;var topmostSlice=this.mostTopLevelSlice;parentStack.push(topmostSlice);while(parentStack.length!==0){var curSlice=parentStack.pop();if(started)
+callback.call(opt_this,curSlice);else
+started=(curSlice.guid===this.guid);for(var i=curSlice.subSlices.length-1;i>=0;i--){parentStack.push(curSlice.subSlices[i]);}}},get subsequentSlices(){var res=[];this.iterateAllSubsequentSlices(function(subseqSlice){res.push(subseqSlice);});return res;},iterateAllAncestors:function(callback,opt_this){var curSlice=this;while(curSlice.parentSlice){curSlice=curSlice.parentSlice;callback.call(opt_this,curSlice);}},get ancestorSlices(){var res=[];this.iterateAllAncestors(function(ancestor){res.push(ancestor);});return res;},get ancestorAndSubsequentSlices(){var res=[];res.push(this);this.iterateAllAncestors(function(aSlice){res.push(aSlice);});this.iterateAllSubsequentSlices(function(sSlice){res.push(sSlice);});return res;},iterateAllDescendents:function(callback,opt_this){this.subSlices.forEach(callback,opt_this);this.subSlices.forEach(function(subSlice){subSlice.iterateAllDescendents(callback,opt_this);},opt_this);},get descendentSlices(){var res=[];this.iterateAllDescendents(function(des){res.push(des);});return res;}};return{Slice:Slice};});'use strict';tr.exportTo('tr.model',function(){var Slice=tr.model.Slice;var SCHEDULING_STATE={DEBUG:'Debug',EXIT_DEAD:'Exit Dead',RUNNABLE:'Runnable',RUNNING:'Running',SLEEPING:'Sleeping',STOPPED:'Stopped',TASK_DEAD:'Task Dead',UNINTR_SLEEP:'Uninterruptible Sleep',UNINTR_SLEEP_WAKE_KILL:'Uninterruptible Sleep | WakeKill',UNINTR_SLEEP_WAKING:'Uninterruptible Sleep | Waking',UNKNOWN:'UNKNOWN',WAKE_KILL:'Wakekill',WAKING:'Waking',ZOMBIE:'Zombie'};function ThreadTimeSlice(thread,schedulingState,cat,start,args,opt_duration){Slice.call(this,cat,schedulingState,this.getColorForState_(schedulingState),start,args,opt_duration);this.thread=thread;this.schedulingState=schedulingState;this.cpuOnWhichThreadWasRunning=undefined;}
+ThreadTimeSlice.prototype={__proto__:Slice.prototype,getColorForState_:function(state){var getColorIdForReservedName=tr.b.ui.getColorIdForReservedName;switch(state){case SCHEDULING_STATE.RUNNABLE:return getColorIdForReservedName('thread_state_runnable');case SCHEDULING_STATE.RUNNING:return getColorIdForReservedName('thread_state_running');case SCHEDULING_STATE.SLEEPING:return getColorIdForReservedName('thread_state_sleeping');case SCHEDULING_STATE.DEBUG:case SCHEDULING_STATE.EXIT_DEAD:case SCHEDULING_STATE.STOPPED:case SCHEDULING_STATE.TASK_DEAD:case SCHEDULING_STATE.UNINTR_SLEEP:case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL:case SCHEDULING_STATE.UNINTR_SLEEP_WAKING:case SCHEDULING_STATE.UNKNOWN:case SCHEDULING_STATE.WAKE_KILL:case SCHEDULING_STATE.WAKING:case SCHEDULING_STATE.ZOMBIE:return getColorIdForReservedName('thread_state_iowait');default:return getColorIdForReservedName('thread_state_unknown');}},get analysisTypeName(){return'tr.c.analysis.ThreadTimeSlice';},getAssociatedCpuSlice:function(){if(!this.cpuOnWhichThreadWasRunning)
 return undefined;var cpuSlices=this.cpuOnWhichThreadWasRunning.slices;for(var i=0;i<cpuSlices.length;i++){var cpuSlice=cpuSlices[i];if(cpuSlice.start!==this.start)
 continue;if(cpuSlice.duration!==this.duration)
 continue;return cpuSlice;}
@@ -2116,14 +2109,14 @@
 if(!cpuSliceWhenLastRunning)
 return undefined;var cpu=cpuSliceWhenLastRunning.cpu;var indexOfSliceOnCpuWhenLastRunning=cpu.indexOf(cpuSliceWhenLastRunning);var nextRunningSlice=cpu.slices[indexOfSliceOnCpuWhenLastRunning+1];if(!nextRunningSlice)
 return undefined;if(Math.abs(nextRunningSlice.start-cpuSliceWhenLastRunning.end)<0.00001)
-return nextRunningSlice;return undefined;}};tv.c.trace_model.EventRegistry.register(ThreadTimeSlice,{name:'threadTimeSlice',pluralName:'threadTimeSlices',singleViewElementName:'tv-c-single-thread-time-slice-sub-view',multiViewElementName:'tv-c-a-multi-thread-time-slice-sub-view'});return{ThreadTimeSlice:ThreadTimeSlice,SCHEDULING_STATE:SCHEDULING_STATE};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Slice=tv.c.trace_model.Slice;function CpuSlice(cat,title,colorId,start,args,opt_duration){Slice.apply(this,arguments);this.threadThatWasRunning=undefined;this.cpu=undefined;}
-CpuSlice.prototype={__proto__:Slice.prototype,get analysisTypeName(){return'tv.c.analysis.CpuSlice';},getAssociatedTimeslice:function(){if(!this.threadThatWasRunning)
+return nextRunningSlice;return undefined;}};tr.model.EventRegistry.register(ThreadTimeSlice,{name:'threadTimeSlice',pluralName:'threadTimeSlices',singleViewElementName:'tr-c-a-single-thread-time-slice-sub-view',multiViewElementName:'tr-c-a-multi-thread-time-slice-sub-view'});return{ThreadTimeSlice:ThreadTimeSlice,SCHEDULING_STATE:SCHEDULING_STATE};});'use strict';tr.exportTo('tr.model',function(){var Slice=tr.model.Slice;function CpuSlice(cat,title,colorId,start,args,opt_duration){Slice.apply(this,arguments);this.threadThatWasRunning=undefined;this.cpu=undefined;}
+CpuSlice.prototype={__proto__:Slice.prototype,get analysisTypeName(){return'tr.c.analysis.CpuSlice';},getAssociatedTimeslice:function(){if(!this.threadThatWasRunning)
 return undefined;var timeSlices=this.threadThatWasRunning.timeSlices;for(var i=0;i<timeSlices.length;i++){var timeSlice=timeSlices[i];if(timeSlice.start!==this.start)
 continue;if(timeSlice.duration!==this.duration)
 continue;return timeSlice;}
-return undefined;}};tv.c.trace_model.EventRegistry.register(CpuSlice,{name:'cpuSlice',pluralName:'cpuSlices',singleViewElementName:'tv-c-single-cpu-slice-sub-view',multiViewElementName:'tv-c-a-multi-cpu-slice-sub-view'});return{CpuSlice:CpuSlice};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Counter=tv.c.trace_model.Counter;var Slice=tv.c.trace_model.Slice;var CpuSlice=tv.c.trace_model.CpuSlice;function Cpu(kernel,number){if(kernel===undefined||number===undefined)
-throw new Error('Missing arguments');this.kernel=kernel;this.cpuNumber=number;this.slices=[];this.counters={};this.bounds=new tv.b.Range();this.samples_=undefined;this.lastActiveTimestamp_=undefined;this.lastActiveThread_=undefined;this.lastActiveName_=undefined;this.lastActiveArgs_=undefined;};Cpu.prototype={iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,tv.c.trace_model.CpuSlice))
-this.slices.forEach(callback,opt_this);if(this.samples_){if(eventTypePredicate.call(opt_this,tv.c.trace_model.Sample))
+return undefined;}};tr.model.EventRegistry.register(CpuSlice,{name:'cpuSlice',pluralName:'cpuSlices',singleViewElementName:'tr-c-a-single-cpu-slice-sub-view',multiViewElementName:'tr-c-a-multi-cpu-slice-sub-view'});return{CpuSlice:CpuSlice};});'use strict';tr.exportTo('tr.model',function(){var Counter=tr.model.Counter;var Slice=tr.model.Slice;var CpuSlice=tr.model.CpuSlice;function Cpu(kernel,number){if(kernel===undefined||number===undefined)
+throw new Error('Missing arguments');this.kernel=kernel;this.cpuNumber=number;this.slices=[];this.counters={};this.bounds=new tr.b.Range();this.samples_=undefined;this.lastActiveTimestamp_=undefined;this.lastActiveThread_=undefined;this.lastActiveName_=undefined;this.lastActiveArgs_=undefined;};Cpu.prototype={iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,tr.model.CpuSlice))
+this.slices.forEach(callback,opt_this);if(this.samples_){if(eventTypePredicate.call(opt_this,tr.model.Sample))
 this.samples_.forEach(callback,opt_this);}},iterateAllChildEventContainers:function(callback,opt_this){for(var id in this.counters)
 callback.call(opt_this,this.counters[id]);},getOrCreateCounter:function(cat,name){var id;if(cat.length)
 id=cat+'.'+name;else
@@ -2135,24 +2128,24 @@
 if(this.samples_&&this.samples_.length){this.bounds.addValue(this.samples_[0].start);this.bounds.addValue(this.samples_[this.samples_.length-1].end);}},createSubSlices:function(){this.samples_=this.kernel.model.samples.filter(function(sample){return sample.cpu==this;},this);},addCategoriesToDict:function(categoriesDict){for(var i=0;i<this.slices.length;i++)
 categoriesDict[this.slices[i].category]=true;for(var id in this.counters)
 categoriesDict[this.counters[id].category]=true;for(var i=0;i<this.samples_.length;i++)
-categoriesDict[this.samples_[i].category]=true;},get userFriendlyName(){return'CPU '+this.cpuNumber;},indexOf:function(cpuSlice){var i=tv.b.findLowIndexInSortedArray(this.slices,function(slice){return slice.start;},cpuSlice.start);if(this.slices[i]!==cpuSlice)
+categoriesDict[this.samples_[i].category]=true;},get userFriendlyName(){return'CPU '+this.cpuNumber;},indexOf:function(cpuSlice){var i=tr.b.findLowIndexInSortedArray(this.slices,function(slice){return slice.start;},cpuSlice.start);if(this.slices[i]!==cpuSlice)
 return undefined;return i;},closeActiveThread:function(end_timestamp,args){if(this.lastActiveThread_==undefined||this.lastActiveThread_==0)
 return;if(end_timestamp<this.lastActiveTimestamp_){throw new Error('The end timestamp of a thread running on CPU '+
 this.cpuNumber+' is before its start timestamp.');}
 for(var key in args){this.lastActiveArgs_[key]=args[key];}
-var duration=end_timestamp-this.lastActiveTimestamp_;var slice=new tv.c.trace_model.CpuSlice('',this.lastActiveName_,tv.b.ui.getColorIdForGeneralPurposeString(this.lastActiveName_),this.lastActiveTimestamp_,this.lastActiveArgs_,duration);slice.cpu=this;this.slices.push(slice);this.lastActiveTimestamp_=undefined;this.lastActiveThread_=undefined;this.lastActiveName_=undefined;this.lastActiveArgs_=undefined;},switchActiveThread:function(timestamp,old_thread_args,new_thread_id,new_thread_name,new_thread_args){this.closeActiveThread(timestamp,old_thread_args);this.lastActiveTimestamp_=timestamp;this.lastActiveThread_=new_thread_id;this.lastActiveName_=new_thread_name;this.lastActiveArgs_=new_thread_args;},get samples(){return this.samples_;}};Cpu.compare=function(x,y){return x.cpuNumber-y.cpuNumber;};return{Cpu:Cpu};});'use strict';tv.exportTo('tv.c.trace_model',function(){function ObjectSnapshot(objectInstance,ts,args){tv.c.trace_model.Event.call(this);this.objectInstance=objectInstance;this.ts=ts;this.args=args;}
-ObjectSnapshot.prototype={__proto__:tv.c.trace_model.Event.prototype,preInitialize:function(){},initialize:function(){},addBoundsToRange:function(range){range.addValue(this.ts);},get userFriendlyName(){return'Snapshot of '+
+var duration=end_timestamp-this.lastActiveTimestamp_;var slice=new tr.model.CpuSlice('',this.lastActiveName_,tr.b.ui.getColorIdForGeneralPurposeString(this.lastActiveName_),this.lastActiveTimestamp_,this.lastActiveArgs_,duration);slice.cpu=this;this.slices.push(slice);this.lastActiveTimestamp_=undefined;this.lastActiveThread_=undefined;this.lastActiveName_=undefined;this.lastActiveArgs_=undefined;},switchActiveThread:function(timestamp,old_thread_args,new_thread_id,new_thread_name,new_thread_args){this.closeActiveThread(timestamp,old_thread_args);this.lastActiveTimestamp_=timestamp;this.lastActiveThread_=new_thread_id;this.lastActiveName_=new_thread_name;this.lastActiveArgs_=new_thread_args;},get samples(){return this.samples_;}};Cpu.compare=function(x,y){return x.cpuNumber-y.cpuNumber;};return{Cpu:Cpu};});'use strict';tr.exportTo('tr.model',function(){function ObjectSnapshot(objectInstance,ts,args){tr.model.Event.call(this);this.objectInstance=objectInstance;this.ts=ts;this.args=args;}
+ObjectSnapshot.prototype={__proto__:tr.model.Event.prototype,preInitialize:function(){},initialize:function(){},addBoundsToRange:function(range){range.addValue(this.ts);},get userFriendlyName(){return'Snapshot of '+
 this.objectInstance.typeName+' '+
 this.objectInstance.id+' @ '+
-tv.c.analysis.tsString(this.ts);}};tv.c.trace_model.EventRegistry.register(ObjectSnapshot,{name:'objectSnapshot',pluralName:'objectSnapshots',singleViewElementName:'tv-c-single-object-snapshot-sub-view',multiViewElementName:'tv-c-multi-object-sub-view'});var options=new tv.b.ExtensionRegistryOptions(tv.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectSnapshot;options.defaultConstructor=ObjectSnapshot;tv.b.decorateExtensionRegistry(ObjectSnapshot,options);return{ObjectSnapshot:ObjectSnapshot};});'use strict';tv.exportTo('tv.c.trace_model',function(){var ObjectSnapshot=tv.c.trace_model.ObjectSnapshot;function ObjectInstance(parent,id,category,name,creationTs,opt_baseTypeName){tv.c.trace_model.Event.call(this);this.parent=parent;this.id=id;this.category=category;this.baseTypeName=opt_baseTypeName?opt_baseTypeName:name;this.name=name;this.creationTs=creationTs;this.creationTsWasExplicit=false;this.deletionTs=Number.MAX_VALUE;this.deletionTsWasExplicit=false;this.colorId=0;this.bounds=new tv.b.Range();this.snapshots=[];this.hasImplicitSnapshots=false;}
-ObjectInstance.prototype={__proto__:tv.c.trace_model.Event.prototype,get typeName(){return this.name;},addBoundsToRange:function(range){range.addRange(this.bounds);},addSnapshot:function(ts,args,opt_name,opt_baseTypeName){if(ts<this.creationTs)
+tr.b.units.tsString(this.ts);}};tr.model.EventRegistry.register(ObjectSnapshot,{name:'objectSnapshot',pluralName:'objectSnapshots',singleViewElementName:'tr-c-a-single-object-snapshot-sub-view',multiViewElementName:'tr-c-a-multi-object-sub-view'});var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectSnapshot;options.defaultConstructor=ObjectSnapshot;tr.b.decorateExtensionRegistry(ObjectSnapshot,options);return{ObjectSnapshot:ObjectSnapshot};});'use strict';tr.exportTo('tr.model',function(){var ObjectSnapshot=tr.model.ObjectSnapshot;function ObjectInstance(parent,id,category,name,creationTs,opt_baseTypeName){tr.model.Event.call(this);this.parent=parent;this.id=id;this.category=category;this.baseTypeName=opt_baseTypeName?opt_baseTypeName:name;this.name=name;this.creationTs=creationTs;this.creationTsWasExplicit=false;this.deletionTs=Number.MAX_VALUE;this.deletionTsWasExplicit=false;this.colorId=0;this.bounds=new tr.b.Range();this.snapshots=[];this.hasImplicitSnapshots=false;}
+ObjectInstance.prototype={__proto__:tr.model.Event.prototype,get typeName(){return this.name;},addBoundsToRange:function(range){range.addRange(this.bounds);},addSnapshot:function(ts,args,opt_name,opt_baseTypeName){if(ts<this.creationTs)
 throw new Error('Snapshots must be >= instance.creationTs');if(ts>=this.deletionTs)
 throw new Error('Snapshots cannot be added after '+'an objects deletion timestamp.');var lastSnapshot;if(this.snapshots.length>0){lastSnapshot=this.snapshots[this.snapshots.length-1];if(lastSnapshot.ts==ts)
 throw new Error('Snapshots already exists at this time!');if(ts<lastSnapshot.ts){throw new Error('Snapshots must be added in increasing timestamp order');}}
 if(opt_name&&(this.name!=opt_name)){if(!opt_baseTypeName)
 throw new Error('Must provide base type name for name update');if(this.baseTypeName!=opt_baseTypeName)
 throw new Error('Cannot update type name: base types dont match');this.name=opt_name;}
-var snapshotConstructor=tv.c.trace_model.ObjectSnapshot.getConstructor(this.category,this.name);var snapshot=new snapshotConstructor(this,ts,args);this.snapshots.push(snapshot);return snapshot;},wasDeleted:function(ts){var lastSnapshot;if(this.snapshots.length>0){lastSnapshot=this.snapshots[this.snapshots.length-1];if(lastSnapshot.ts>ts)
+var snapshotConstructor=tr.model.ObjectSnapshot.getConstructor(this.category,this.name);var snapshot=new snapshotConstructor(this,ts,args);this.snapshots.push(snapshot);return snapshot;},wasDeleted:function(ts){var lastSnapshot;if(this.snapshots.length>0){lastSnapshot=this.snapshots[this.snapshots.length-1];if(lastSnapshot.ts>ts)
 throw new Error('Instance cannot be deleted at ts='+
 ts+'. A snapshot exists that is older.');}
 this.deletionTs=ts;this.deletionTsWasExplicit=true;},preInitialize:function(){for(var i=0;i<this.snapshots.length;i++)
@@ -2160,17 +2153,17 @@
 this.snapshots[i].initialize();},getSnapshotAt:function(ts){if(ts<this.creationTs){if(this.creationTsWasExplicit)
 throw new Error('ts must be within lifetime of this instance');return this.snapshots[0];}
 if(ts>this.deletionTs)
-throw new Error('ts must be within lifetime of this instance');var snapshots=this.snapshots;var i=tv.b.findIndexInSortedIntervals(snapshots,function(snapshot){return snapshot.ts;},function(snapshot,i){if(i==snapshots.length-1)
+throw new Error('ts must be within lifetime of this instance');var snapshots=this.snapshots;var i=tr.b.findIndexInSortedIntervals(snapshots,function(snapshot){return snapshot.ts;},function(snapshot,i){if(i==snapshots.length-1)
 return snapshots[i].objectInstance.deletionTs;return snapshots[i+1].ts-snapshots[i].ts;},ts);if(i<0){return this.snapshots[0];}
 if(i>=this.snapshots.length)
 return this.snapshots[this.snapshots.length-1];return this.snapshots[i];},updateBounds:function(){this.bounds.reset();this.bounds.addValue(this.creationTs);if(this.deletionTs!=Number.MAX_VALUE)
 this.bounds.addValue(this.deletionTs);else if(this.snapshots.length>0)
 this.bounds.addValue(this.snapshots[this.snapshots.length-1].ts);},shiftTimestampsForward:function(amount){this.creationTs+=amount;if(this.deletionTs!=Number.MAX_VALUE)
-this.deletionTs+=amount;this.snapshots.forEach(function(snapshot){snapshot.ts+=amount;});},get userFriendlyName(){return this.typeName+' object '+this.id;}};tv.c.trace_model.EventRegistry.register(ObjectInstance,{name:'objectInstance',pluralName:'objectInstances',singleViewElementName:'tv-c-single-object-instance-sub-view',multiViewElementName:'tv-c-multi-object-sub-view'});var options=new tv.b.ExtensionRegistryOptions(tv.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectInstance;options.defaultConstructor=ObjectInstance;tv.b.decorateExtensionRegistry(ObjectInstance,options);return{ObjectInstance:ObjectInstance};});'use strict';tv.exportTo('tv.c.trace_model',function(){function TimeToObjectInstanceMap(createObjectInstanceFunction,parent,id){this.createObjectInstanceFunction_=createObjectInstanceFunction;this.parent=parent;this.id=id;this.instances=[];}
+this.deletionTs+=amount;this.snapshots.forEach(function(snapshot){snapshot.ts+=amount;});},get userFriendlyName(){return this.typeName+' object '+this.id;}};tr.model.EventRegistry.register(ObjectInstance,{name:'objectInstance',pluralName:'objectInstances',singleViewElementName:'tr-c-a-single-object-instance-sub-view',multiViewElementName:'tr-c-a-multi-object-sub-view'});var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectInstance;options.defaultConstructor=ObjectInstance;tr.b.decorateExtensionRegistry(ObjectInstance,options);return{ObjectInstance:ObjectInstance};});'use strict';tr.exportTo('tr.model',function(){function TimeToObjectInstanceMap(createObjectInstanceFunction,parent,id){this.createObjectInstanceFunction_=createObjectInstanceFunction;this.parent=parent;this.id=id;this.instances=[];}
 TimeToObjectInstanceMap.prototype={idWasCreated:function(category,name,ts){if(this.instances.length==0){this.instances.push(this.createObjectInstanceFunction_(this.parent,this.id,category,name,ts));this.instances[0].creationTsWasExplicit=true;return this.instances[0];}
 var lastInstance=this.instances[this.instances.length-1];if(ts<lastInstance.deletionTs){throw new Error('Mutation of the TimeToObjectInstanceMap must be '+'done in ascending timestamp order.');}
 lastInstance=this.createObjectInstanceFunction_(this.parent,this.id,category,name,ts);lastInstance.creationTsWasExplicit=true;this.instances.push(lastInstance);return lastInstance;},addSnapshot:function(category,name,ts,args,opt_baseTypeName){if(this.instances.length==0){this.instances.push(this.createObjectInstanceFunction_(this.parent,this.id,category,name,ts,opt_baseTypeName));}
-var i=tv.b.findIndexInSortedIntervals(this.instances,function(inst){return inst.creationTs;},function(inst){return inst.deletionTs-inst.creationTs;},ts);var instance;if(i<0){instance=this.instances[0];if(ts>instance.deletionTs||instance.creationTsWasExplicit){throw new Error('At the provided timestamp, no instance was still alive');}
+var i=tr.b.findIndexInSortedIntervals(this.instances,function(inst){return inst.creationTs;},function(inst){return inst.deletionTs-inst.creationTs;},ts);var instance;if(i<0){instance=this.instances[0];if(ts>instance.deletionTs||instance.creationTsWasExplicit){throw new Error('At the provided timestamp, no instance was still alive');}
 if(instance.snapshots.length!=0){throw new Error('Cannot shift creationTs forward, '+'snapshots have been added. First snap was at ts='+
 instance.snapshots[0].ts+' and creationTs was '+
 instance.creationTs);}
@@ -2184,17 +2177,17 @@
 var lastInstance=this.instances[this.instances.length-1];if(ts<lastInstance.creationTs)
 throw new Error('Cannot delete a id before it was crated');if(lastInstance.deletionTs==Number.MAX_VALUE){lastInstance.wasDeleted(ts);return lastInstance;}
 if(ts<lastInstance.deletionTs)
-throw new Error('id was already deleted earlier.');lastInstance=this.createObjectInstanceFunction_(this.parent,this.id,category,name,ts);this.instances.push(lastInstance);lastInstance.wasDeleted(ts);return lastInstance;},getInstanceAt:function(ts){var i=tv.b.findIndexInSortedIntervals(this.instances,function(inst){return inst.creationTs;},function(inst){return inst.deletionTs-inst.creationTs;},ts);if(i<0){if(this.instances[0].creationTsWasExplicit)
+throw new Error('id was already deleted earlier.');lastInstance=this.createObjectInstanceFunction_(this.parent,this.id,category,name,ts);this.instances.push(lastInstance);lastInstance.wasDeleted(ts);return lastInstance;},getInstanceAt:function(ts){var i=tr.b.findIndexInSortedIntervals(this.instances,function(inst){return inst.creationTs;},function(inst){return inst.deletionTs-inst.creationTs;},ts);if(i<0){if(this.instances[0].creationTsWasExplicit)
 return undefined;return this.instances[0];}else if(i>=this.instances.length){return undefined;}
 return this.instances[i];},logToConsole:function(){for(var i=0;i<this.instances.length;i++){var instance=this.instances[i];var cEF='';var dEF='';if(instance.creationTsWasExplicit)
 cEF='(explicitC)';if(instance.deletionTsWasExplicit)
-dEF='(explicit)';console.log(instance.creationTs,cEF,instance.deletionTs,dEF,instance.category,instance.name,instance.snapshots.length+' snapshots');}}};return{TimeToObjectInstanceMap:TimeToObjectInstanceMap};});'use strict';tv.exportTo('tv.c.trace_model',function(){var ObjectInstance=tv.c.trace_model.ObjectInstance;var ObjectSnapshot=tv.c.trace_model.ObjectSnapshot;function ObjectCollection(parent){tv.c.trace_model.EventContainer.call(this);this.parent=parent;this.bounds=new tv.b.Range();this.instanceMapsById_={};this.instancesByTypeName_={};this.createObjectInstance_=this.createObjectInstance_.bind(this);}
-ObjectCollection.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,iterateAllChildEventContainers:function(callback,opt_this){},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){var bI=!!eventTypePredicate.call(opt_this,ObjectInstance);var bS=!!eventTypePredicate.call(opt_this,ObjectSnapshot);if(bI===false&&bS===false)
+dEF='(explicit)';console.log(instance.creationTs,cEF,instance.deletionTs,dEF,instance.category,instance.name,instance.snapshots.length+' snapshots');}}};return{TimeToObjectInstanceMap:TimeToObjectInstanceMap};});'use strict';tr.exportTo('tr.model',function(){var ObjectInstance=tr.model.ObjectInstance;var ObjectSnapshot=tr.model.ObjectSnapshot;function ObjectCollection(parent){tr.model.EventContainer.call(this);this.parent=parent;this.bounds=new tr.b.Range();this.instanceMapsById_={};this.instancesByTypeName_={};this.createObjectInstance_=this.createObjectInstance_.bind(this);}
+ObjectCollection.prototype={__proto__:tr.model.EventContainer.prototype,iterateAllChildEventContainers:function(callback,opt_this){},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){var bI=!!eventTypePredicate.call(opt_this,ObjectInstance);var bS=!!eventTypePredicate.call(opt_this,ObjectSnapshot);if(bI===false&&bS===false)
 return;this.iterObjectInstances(function(instance){if(bI)
 callback.call(opt_this,instance);if(bS)
-instance.snapshots.forEach(callback,opt_this);},opt_this);},createObjectInstance_:function(parent,id,category,name,creationTs,opt_baseTypeName){var constructor=tv.c.trace_model.ObjectInstance.getConstructor(category,name);var instance=new constructor(parent,id,category,name,creationTs,opt_baseTypeName);var typeName=instance.typeName;var instancesOfTypeName=this.instancesByTypeName_[typeName];if(!instancesOfTypeName){instancesOfTypeName=[];this.instancesByTypeName_[typeName]=instancesOfTypeName;}
+instance.snapshots.forEach(callback,opt_this);},opt_this);},createObjectInstance_:function(parent,id,category,name,creationTs,opt_baseTypeName){var constructor=tr.model.ObjectInstance.getConstructor(category,name);var instance=new constructor(parent,id,category,name,creationTs,opt_baseTypeName);var typeName=instance.typeName;var instancesOfTypeName=this.instancesByTypeName_[typeName];if(!instancesOfTypeName){instancesOfTypeName=[];this.instancesByTypeName_[typeName]=instancesOfTypeName;}
 instancesOfTypeName.push(instance);return instance;},getOrCreateInstanceMap_:function(id){var instanceMap=this.instanceMapsById_[id];if(instanceMap)
-return instanceMap;instanceMap=new tv.c.trace_model.TimeToObjectInstanceMap(this.createObjectInstance_,this.parent,id);this.instanceMapsById_[id]=instanceMap;return instanceMap;},idWasCreated:function(id,category,name,ts){var instanceMap=this.getOrCreateInstanceMap_(id);return instanceMap.idWasCreated(category,name,ts);},addSnapshot:function(id,category,name,ts,args,opt_baseTypeName){var instanceMap=this.getOrCreateInstanceMap_(id);var snapshot=instanceMap.addSnapshot(category,name,ts,args,opt_baseTypeName);if(snapshot.objectInstance.category!=category){var msg='Added snapshot name='+name+' with cat='+category+' impossible. It instance was created/snapshotted with cat='+
+return instanceMap;instanceMap=new tr.model.TimeToObjectInstanceMap(this.createObjectInstance_,this.parent,id);this.instanceMapsById_[id]=instanceMap;return instanceMap;},idWasCreated:function(id,category,name,ts){var instanceMap=this.getOrCreateInstanceMap_(id);return instanceMap.idWasCreated(category,name,ts);},addSnapshot:function(id,category,name,ts,args,opt_baseTypeName){var instanceMap=this.getOrCreateInstanceMap_(id);var snapshot=instanceMap.addSnapshot(category,name,ts,args,opt_baseTypeName);if(snapshot.objectInstance.category!=category){var msg='Added snapshot name='+name+' with cat='+category+' impossible. It instance was created/snapshotted with cat='+
 snapshot.objectInstance.category+' name='+
 snapshot.objectInstance.name;throw new Error(msg);}
 if(opt_baseTypeName&&snapshot.objectInstance.baseTypeName!=opt_baseTypeName){throw new Error('Could not add snapshot with baseTypeName='+
@@ -2207,18 +2200,18 @@
 deletedInstance.category+' but the delete command '+'had cat='+category;throw new Error(msg);}
 if(deletedInstance.baseTypeName!=name){throw new Error('Deletion requested for name='+
 name+' could not proceed: '+'An existing object with baseTypeName='+
-deletedInstance.baseTypeName+' existed.');}},autoDeleteObjects:function(maxTimestamp){tv.b.iterItems(this.instanceMapsById_,function(id,i2imap){var lastInstance=i2imap.lastInstance;if(lastInstance.deletionTs!=Number.MAX_VALUE)
+deletedInstance.baseTypeName+' existed.');}},autoDeleteObjects:function(maxTimestamp){tr.b.iterItems(this.instanceMapsById_,function(id,i2imap){var lastInstance=i2imap.lastInstance;if(lastInstance.deletionTs!=Number.MAX_VALUE)
 return;i2imap.idWasDeleted(lastInstance.category,lastInstance.name,maxTimestamp);lastInstance.deletionTsWasExplicit=false;});},getObjectInstanceAt:function(id,ts){var instanceMap=this.instanceMapsById_[id];if(!instanceMap)
 return undefined;return instanceMap.getInstanceAt(ts);},getSnapshotAt:function(id,ts){var instance=this.getObjectInstanceAt(id,ts);if(!instance)
-return undefined;return instance.getSnapshotAt(ts);},iterObjectInstances:function(iter,opt_this){opt_this=opt_this||this;tv.b.iterItems(this.instanceMapsById_,function(id,i2imap){i2imap.instances.forEach(iter,opt_this);});},getAllObjectInstances:function(){var instances=[];this.iterObjectInstances(function(i){instances.push(i);});return instances;},getAllInstancesNamed:function(name){return this.instancesByTypeName_[name];},getAllInstancesByTypeName:function(){return this.instancesByTypeName_;},preInitializeAllObjects:function(){this.iterObjectInstances(function(instance){instance.preInitialize();});},initializeAllObjects:function(){this.iterObjectInstances(function(instance){instance.initialize();});},initializeInstances:function(){this.iterObjectInstances(function(instance){instance.initialize();});},updateBounds:function(){this.bounds.reset();this.iterObjectInstances(function(instance){instance.updateBounds();this.bounds.addRange(instance.bounds);},this);},shiftTimestampsForward:function(amount){this.iterObjectInstances(function(instance){instance.shiftTimestampsForward(amount);});},addCategoriesToDict:function(categoriesDict){this.iterObjectInstances(function(instance){categoriesDict[instance.category]=true;});}};return{ObjectCollection:ObjectCollection};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Slice=tv.c.trace_model.Slice;function ThreadSlice(cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration){Slice.call(this,cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration);this.subSlices=[];}
-ThreadSlice.prototype={__proto__:Slice.prototype};tv.c.trace_model.EventRegistry.register(ThreadSlice,{name:'slice',pluralName:'slices',singleViewElementName:'tv-c-a-single-thread-slice-sub-view',multiViewElementName:'tv-c-a-multi-thread-slice-sub-view'});return{ThreadSlice:ThreadSlice};});'use strict';tv.exportTo('tv.b.ui',function(){function boundChannel(v){return Math.min(255,Math.max(0,Math.floor(v)));}
+return undefined;return instance.getSnapshotAt(ts);},iterObjectInstances:function(iter,opt_this){opt_this=opt_this||this;tr.b.iterItems(this.instanceMapsById_,function(id,i2imap){i2imap.instances.forEach(iter,opt_this);});},getAllObjectInstances:function(){var instances=[];this.iterObjectInstances(function(i){instances.push(i);});return instances;},getAllInstancesNamed:function(name){return this.instancesByTypeName_[name];},getAllInstancesByTypeName:function(){return this.instancesByTypeName_;},preInitializeAllObjects:function(){this.iterObjectInstances(function(instance){instance.preInitialize();});},initializeAllObjects:function(){this.iterObjectInstances(function(instance){instance.initialize();});},initializeInstances:function(){this.iterObjectInstances(function(instance){instance.initialize();});},updateBounds:function(){this.bounds.reset();this.iterObjectInstances(function(instance){instance.updateBounds();this.bounds.addRange(instance.bounds);},this);},shiftTimestampsForward:function(amount){this.iterObjectInstances(function(instance){instance.shiftTimestampsForward(amount);});},addCategoriesToDict:function(categoriesDict){this.iterObjectInstances(function(instance){categoriesDict[instance.category]=true;});}};return{ObjectCollection:ObjectCollection};});'use strict';tr.exportTo('tr.model',function(){var Slice=tr.model.Slice;function ThreadSlice(cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration){Slice.call(this,cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration);this.subSlices=[];}
+ThreadSlice.prototype={__proto__:Slice.prototype};tr.model.EventRegistry.register(ThreadSlice,{name:'slice',pluralName:'slices',singleViewElementName:'tr-c-a-single-thread-slice-sub-view',multiViewElementName:'tr-c-a-multi-thread-slice-sub-view'});return{ThreadSlice:ThreadSlice};});'use strict';tr.exportTo('tr.b.ui',function(){function boundChannel(v){return Math.min(255,Math.max(0,Math.floor(v)));}
 function brightenColor(c){var k;if(c.r>=240&&c.g>=240&&c.b>=240)
 k=0.80;else
 k=1.45;return{r:boundChannel(c.r*k),g:boundChannel(c.g*k),b:boundChannel(c.b*k)};}
 function desaturateColor(c){var value=boundChannel((c.r+c.g+c.b)/3);return{r:value,g:value,b:value};}
 function colorToRGBString(c){return'rgb('+c.r+','+c.g+','+c.b+')';}
 function colorToRGBAString(c,a){return'rgba('+c.r+','+c.g+','+c.b+','+a+')';}
-return{brightenColor:brightenColor,desaturateColor:desaturateColor,colorToRGBString:colorToRGBString,colorToRGBAString:colorToRGBAString};});'use strict';tv.exportTo('tv.b.ui',function(){var colorToRGBString=tv.b.ui.colorToRGBString;var colorToRGBAString=tv.b.ui.colorToRGBAString;var generalPurposeColors=[{r:138,g:113,b:152},{r:175,g:112,b:133},{r:127,g:135,b:225},{r:93,g:81,b:137},{r:116,g:143,b:119},{r:178,g:214,b:122},{r:87,g:109,b:147},{r:119,g:155,b:95},{r:114,g:180,b:160},{r:132,g:85,b:103},{r:157,g:210,b:150},{r:148,g:94,b:86},{r:164,g:108,b:138},{r:139,g:191,b:150},{r:110,g:99,b:145},{r:80,g:129,b:109},{r:125,g:140,b:149},{r:93,g:124,b:132},{r:140,g:85,b:140},{r:104,g:163,b:162},{r:132,g:141,b:178},{r:131,g:105,b:147},{r:135,g:183,b:98},{r:152,g:134,b:177},{r:141,g:188,b:141},{r:133,g:160,b:210},{r:126,g:186,b:148},{r:112,g:198,b:205},{r:180,g:122,b:195},{r:203,g:144,b:152}];var reservedColorsByName={thread_state_iowait:{r:182,g:125,b:143},thread_state_running:{r:126,g:200,b:148},thread_state_runnable:{r:133,g:160,b:210},thread_state_sleeping:{r:240,g:240,b:240},thread_state_unknown:{r:199,g:155,b:125},memory_dump:{r:0,g:0,b:180},generic_work:{r:125,g:125,b:125},good:{r:0,g:125,b:0},bad:{r:180,g:125,b:0},terrible:{r:180,g:0,b:0},black:{r:0,g:0,b:0}};var numGeneralPurposeColorIds=generalPurposeColors.length;var numReservedColorIds=tv.b.dictionaryLength(reservedColorsByName);var paletteRaw=(function(){var paletteBase=[];paletteBase.push.apply(paletteBase,generalPurposeColors);paletteBase.push.apply(paletteBase,tv.b.dictionaryValues(reservedColorsByName));return paletteBase.concat(paletteBase.map(tv.b.ui.brightenColor),paletteBase.map(tv.b.ui.desaturateColor));})();var palette=paletteRaw.map(colorToRGBString);var highlightIdBoost=paletteRaw.length/3;var desaturateIdBoost=(paletteRaw.length/3)*2;var reservedColorNameToIdMap=(function(){var m={};var i=generalPurposeColors.length;tv.b.iterItems(reservedColorsByName,function(key,value){m[key]=i++;});return m;})();function getStringHash(name){var hash=0;for(var i=0;i<name.length;++i)
+return{brightenColor:brightenColor,desaturateColor:desaturateColor,colorToRGBString:colorToRGBString,colorToRGBAString:colorToRGBAString};});'use strict';tr.exportTo('tr.b.ui',function(){var colorToRGBString=tr.b.ui.colorToRGBString;var colorToRGBAString=tr.b.ui.colorToRGBAString;var generalPurposeColors=[{r:138,g:113,b:152},{r:175,g:112,b:133},{r:127,g:135,b:225},{r:93,g:81,b:137},{r:116,g:143,b:119},{r:178,g:214,b:122},{r:87,g:109,b:147},{r:119,g:155,b:95},{r:114,g:180,b:160},{r:132,g:85,b:103},{r:157,g:210,b:150},{r:148,g:94,b:86},{r:164,g:108,b:138},{r:139,g:191,b:150},{r:110,g:99,b:145},{r:80,g:129,b:109},{r:125,g:140,b:149},{r:93,g:124,b:132},{r:140,g:85,b:140},{r:104,g:163,b:162},{r:132,g:141,b:178},{r:131,g:105,b:147},{r:135,g:183,b:98},{r:152,g:134,b:177},{r:141,g:188,b:141},{r:133,g:160,b:210},{r:126,g:186,b:148},{r:112,g:198,b:205},{r:180,g:122,b:195},{r:203,g:144,b:152}];var reservedColorsByName={thread_state_iowait:{r:182,g:125,b:143},thread_state_running:{r:126,g:200,b:148},thread_state_runnable:{r:133,g:160,b:210},thread_state_sleeping:{r:240,g:240,b:240},thread_state_unknown:{r:199,g:155,b:125},memory_dump:{r:0,g:0,b:180},generic_work:{r:125,g:125,b:125},good:{r:0,g:125,b:0},bad:{r:180,g:125,b:0},terrible:{r:180,g:0,b:0},black:{r:0,g:0,b:0},rail_response:{r:67,g:135,b:253},rail_animate:{r:244,g:74,b:63},rail_idle:{r:238,g:142,b:0},rail_load:{r:13,g:168,b:97}};var numGeneralPurposeColorIds=generalPurposeColors.length;var numReservedColorIds=tr.b.dictionaryLength(reservedColorsByName);var paletteRaw=(function(){var paletteBase=[];paletteBase.push.apply(paletteBase,generalPurposeColors);paletteBase.push.apply(paletteBase,tr.b.dictionaryValues(reservedColorsByName));return paletteBase.concat(paletteBase.map(tr.b.ui.brightenColor),paletteBase.map(tr.b.ui.desaturateColor));})();var palette=paletteRaw.map(colorToRGBString);var highlightIdBoost=paletteRaw.length/3;var desaturateIdBoost=(paletteRaw.length/3)*2;var reservedColorNameToIdMap=(function(){var m={};var i=generalPurposeColors.length;tr.b.iterItems(reservedColorsByName,function(key,value){m[key]=i++;});return m;})();function getStringHash(name){var hash=0;for(var i=0;i<name.length;++i)
 hash=(hash+37*hash+11*name.charCodeAt(i))%0xFFFFFFFF;return hash;}
 function getColorPalette(){return palette;}
 function getRawColorPalette(){return paletteRaw;}
@@ -2228,33 +2221,33 @@
 throw new Error('Unrecognized color ')+name;return id;}
 var stringColorIdCache={};function getColorIdForGeneralPurposeString(string){if(stringColorIdCache[string]===undefined){var hash=getStringHash(string);stringColorIdCache[string]=hash%numGeneralPurposeColorIds;}
 return stringColorIdCache[string];}
-var paletteProperties={numGeneralPurposeColorIds:numGeneralPurposeColorIds,highlightIdBoost:highlightIdBoost,desaturateIdBoost:desaturateIdBoost};return{getRawColorPalette:getRawColorPalette,getColorPalette:getColorPalette,paletteProperties:paletteProperties,getColorPaletteHighlightIdBoost:getColorPaletteHighlightIdBoost,getColorPaletteDesaturateIdBoost:getColorPaletteDesaturateIdBoost,getColorIdForReservedName:getColorIdForReservedName,getStringHash:getStringHash,getColorIdForGeneralPurposeString:getColorIdForGeneralPurposeString};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Slice=tv.c.trace_model.Slice;function getSliceLo(s){return s.start;}
+var paletteProperties={numGeneralPurposeColorIds:numGeneralPurposeColorIds,highlightIdBoost:highlightIdBoost,desaturateIdBoost:desaturateIdBoost};return{getRawColorPalette:getRawColorPalette,getColorPalette:getColorPalette,paletteProperties:paletteProperties,getColorPaletteHighlightIdBoost:getColorPaletteHighlightIdBoost,getColorPaletteDesaturateIdBoost:getColorPaletteDesaturateIdBoost,getColorIdForReservedName:getColorIdForReservedName,getStringHash:getStringHash,getColorIdForGeneralPurposeString:getColorIdForGeneralPurposeString};});'use strict';tr.exportTo('tr.model',function(){var Slice=tr.model.Slice;function getSliceLo(s){return s.start;}
 function getSliceHi(s){return s.end;}
-function SliceGroup(parentThread,opt_sliceConstructor,opt_name){this.guid_=tv.b.GUID.allocate();this.parentThread_=parentThread;var sliceConstructor=opt_sliceConstructor||Slice;this.sliceConstructor=sliceConstructor;this.openPartialSlices_=[];this.slices=[];this.bounds=new tv.b.Range();this.topLevelSlices=[];this.haveTopLevelSlicesBeenBuilt=false;this.name_=opt_name;}
-SliceGroup.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,get guid(){return this.guid_;},get parentThread(){return this.parentThread_;},get model(){return this.parentThread_.parent.model;},get stableId(){return this.parentThread_.stableId+'.SliceGroup';},getSettingsKey:function(){if(!this.name_)
-return undefined;var parentKey=this.parentThread_.getSettingsKey();if(!parentKey)
-return undefined;return parentKey+'.'+this.name;},get length(){return this.slices.length;},pushSlice:function(slice){this.haveTopLevelSlicesBeenBuilt=false;this.slices.push(slice);return slice;},pushSlices:function(slices){this.haveTopLevelSlicesBeenBuilt=false;this.slices.push.apply(this.slices,slices);},beginSlice:function(category,title,ts,opt_args,opt_tts){if(this.openPartialSlices_.length){var prevSlice=this.openPartialSlices_[this.openPartialSlices_.length-1];if(ts<prevSlice.start)
+function SliceGroup(parentContainer,opt_sliceConstructor,opt_name){this.guid_=tr.b.GUID.allocate();this.parentContainer_=parentContainer;var sliceConstructor=opt_sliceConstructor||Slice;this.sliceConstructor=sliceConstructor;this.openPartialSlices_=[];this.slices=[];this.bounds=new tr.b.Range();this.topLevelSlices=[];this.haveTopLevelSlicesBeenBuilt=false;this.name_=opt_name;}
+SliceGroup.prototype={__proto__:tr.model.EventContainer.prototype,get guid(){return this.guid_;},get parentContainer(){return this.parentContainer_;},get model(){return this.parentContainer_.parent.model;},get stableId(){return this.parentContainer_.stableId+'.SliceGroup';},getSettingsKey:function(){if(!this.name_)
+return undefined;var parentKey=this.parentContainer_.getSettingsKey();if(!parentKey)
+return undefined;return parentKey+'.'+this.name;},get length(){return this.slices.length;},pushSlice:function(slice){this.haveTopLevelSlicesBeenBuilt=false;slice.parentContainer=this.parentContainer_;this.slices.push(slice);return slice;},pushSlices:function(slices){this.haveTopLevelSlicesBeenBuilt=false;slices.forEach(function(slice){slice.parentContainer=this.parentContainer_;this.slices.push(slice);},this);},beginSlice:function(category,title,ts,opt_args,opt_tts){if(this.openPartialSlices_.length){var prevSlice=this.openPartialSlices_[this.openPartialSlices_.length-1];if(ts<prevSlice.start)
 throw new Error('Slices must be added in increasing timestamp order');}
-var colorId=tv.b.ui.getColorIdForGeneralPurposeString(title);var slice=new this.sliceConstructor(category,title,colorId,ts,opt_args?opt_args:{},null,opt_tts);this.openPartialSlices_.push(slice);slice.didNotFinish=true;this.pushSlice(slice);return slice;},isTimestampValidForBeginOrEnd:function(ts){if(!this.openPartialSlices_.length)
+var colorId=tr.b.ui.getColorIdForGeneralPurposeString(title);var slice=new this.sliceConstructor(category,title,colorId,ts,opt_args?opt_args:{},null,opt_tts);this.openPartialSlices_.push(slice);slice.didNotFinish=true;this.pushSlice(slice);return slice;},isTimestampValidForBeginOrEnd:function(ts){if(!this.openPartialSlices_.length)
 return true;var top=this.openPartialSlices_[this.openPartialSlices_.length-1];return ts>=top.start;},get openSliceCount(){return this.openPartialSlices_.length;},get mostRecentlyOpenedPartialSlice(){if(!this.openPartialSlices_.length)
 return undefined;return this.openPartialSlices_[this.openPartialSlices_.length-1];},endSlice:function(ts,opt_tts){if(!this.openSliceCount)
 throw new Error('endSlice called without an open slice');var slice=this.openPartialSlices_[this.openSliceCount-1];this.openPartialSlices_.splice(this.openSliceCount-1,1);if(ts<slice.start)
 throw new Error('Slice '+slice.title+' end time is before its start.');slice.duration=ts-slice.start;slice.didNotFinish=false;if(opt_tts&&slice.cpuStart!==undefined)
-slice.cpuDuration=opt_tts-slice.cpuStart;return slice;},pushCompleteSlice:function(category,title,ts,duration,tts,cpuDuration,opt_args){var colorId=tv.b.ui.getColorIdForGeneralPurposeString(title);var slice=new this.sliceConstructor(category,title,colorId,ts,opt_args?opt_args:{},duration,tts,cpuDuration);if(duration===undefined)
+slice.cpuDuration=opt_tts-slice.cpuStart;return slice;},pushCompleteSlice:function(category,title,ts,duration,tts,cpuDuration,opt_args){var colorId=tr.b.ui.getColorIdForGeneralPurposeString(title);var slice=new this.sliceConstructor(category,title,colorId,ts,opt_args?opt_args:{},duration,tts,cpuDuration);if(duration===undefined)
 slice.didNotFinish=true;this.pushSlice(slice);return slice;},autoCloseOpenSlices:function(opt_maxTimestamp){if(!opt_maxTimestamp){this.updateBounds();opt_maxTimestamp=this.bounds.max;}
 for(var sI=0;sI<this.slices.length;sI++){var slice=this.slices[sI];if(slice.didNotFinish)
 slice.duration=opt_maxTimestamp-slice.start;}
 this.openPartialSlices_=[];},shiftTimestampsForward:function(amount){for(var sI=0;sI<this.slices.length;sI++){var slice=this.slices[sI];slice.start=(slice.start+amount);}},updateBounds:function(){this.bounds.reset();for(var i=0;i<this.slices.length;i++){this.bounds.addValue(this.slices[i].start);this.bounds.addValue(this.slices[i].end);}},copySlice:function(slice){var newSlice=new this.sliceConstructor(slice.category,slice.title,slice.colorId,slice.start,slice.args,slice.duration,slice.cpuStart,slice.cpuDuration);newSlice.didNotFinish=slice.didNotFinish;return newSlice;},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,this.sliceConstructor))
 this.slices.forEach(callback,opt_this);},iterateAllChildEventContainers:function(callback,opt_this){},getSlicesOfName:function(title){var slices=[];for(var i=0;i<this.slices.length;i++){if(this.slices[i].title==title){slices.push(this.slices[i]);}}
-return slices;},iterSlicesInTimeRange:function(callback,start,end){var ret=[];tv.b.iterateOverIntersectingIntervals(this.topLevelSlices,function(s){return s.start;},function(s){return s.duration;},start,end,function(topLevelSlice){callback(topLevelSlice);topLevelSlice.iterateAllDescendents(callback);});return ret;},findSliceAtTs:function(ts){if(!this.haveTopLevelSlicesBeenBuilt)
-throw new Error('Nope');var i=tv.b.findIndexInSortedClosedIntervals(this.topLevelSlices,getSliceLo,getSliceHi,ts);if(i==-1||i==this.topLevelSlices.length)
-return undefined;var curSlice=this.topLevelSlices[i];while(true){var i=tv.b.findIndexInSortedClosedIntervals(curSlice.subSlices,getSliceLo,getSliceHi,ts);if(i==-1||i==curSlice.subSlices.length)
-return curSlice;curSlice=curSlice.subSlices[i];}},findNextSliceAfter:function(ts,refGuid){var i=tv.b.findLowIndexInSortedArray(this.slices,getSliceLo,ts);if(i===this.slices.length)
+return slices;},iterSlicesInTimeRange:function(callback,start,end){var ret=[];tr.b.iterateOverIntersectingIntervals(this.topLevelSlices,function(s){return s.start;},function(s){return s.duration;},start,end,function(topLevelSlice){callback(topLevelSlice);topLevelSlice.iterateAllDescendents(callback);});return ret;},findSliceAtTs:function(ts){if(!this.haveTopLevelSlicesBeenBuilt)
+throw new Error('Nope');var i=tr.b.findIndexInSortedClosedIntervals(this.topLevelSlices,getSliceLo,getSliceHi,ts);if(i==-1||i==this.topLevelSlices.length)
+return undefined;var curSlice=this.topLevelSlices[i];while(true){var i=tr.b.findIndexInSortedClosedIntervals(curSlice.subSlices,getSliceLo,getSliceHi,ts);if(i==-1||i==curSlice.subSlices.length)
+return curSlice;curSlice=curSlice.subSlices[i];}},findNextSliceAfter:function(ts,refGuid){var i=tr.b.findLowIndexInSortedArray(this.slices,getSliceLo,ts);if(i===this.slices.length)
 return undefined;for(;i<this.slices.length;i++){var slice=this.slices[i];if(slice.start>ts)
 return slice;if(slice.guid<=refGuid)
 continue;return slice;}
-return undefined;},createSubSlices:function(){this.haveTopLevelSlicesBeenBuilt=true;this.createSubSlicesImpl_();if(this.parentThread.timeSlices)
-this.addCpuTimeToSubslices_(this.parentThread.timeSlices);this.slices.forEach(function(slice){var selfTime=slice.duration;for(var i=0;i<slice.subSlices.length;i++)
+return undefined;},createSubSlices:function(){this.haveTopLevelSlicesBeenBuilt=true;this.createSubSlicesImpl_();if(this.parentContainer.timeSlices)
+this.addCpuTimeToSubslices_(this.parentContainer.timeSlices);this.slices.forEach(function(slice){var selfTime=slice.duration;for(var i=0;i<slice.subSlices.length;i++)
 selfTime-=slice.subSlices[i].duration;slice.selfTime=selfTime;if(slice.cpuDuration===undefined)
 return;var cpuSelfTime=slice.cpuDuration;for(var i=0;i<slice.subSlices.length;i++){if(slice.subSlices[i].cpuDuration!==undefined)
 cpuSelfTime-=slice.subSlices[i].cpuDuration;}
@@ -2269,40 +2262,39 @@
 var originalSlices=this.slices;ops.sort(function(ix,iy){var x=originalSlices[ix];var y=originalSlices[iy];if(x.start!=y.start)
 return x.start-y.start;return ix-iy;});var slices=new Array(this.slices.length);for(var i=0;i<ops.length;i++){slices[i]=originalSlices[ops[i]];}
 var rootSlice=slices[0];this.topLevelSlices=[];this.topLevelSlices.push(rootSlice);for(var i=1;i<slices.length;i++){var slice=slices[i];if(!addSliceIfBounds(rootSlice,slice)){rootSlice=slice;this.topLevelSlices.push(rootSlice);}}
-this.slices=slices;},addCpuTimeToSubslices_:function(timeSlices){var SCHEDULING_STATE=tv.c.trace_model.SCHEDULING_STATE;var sliceIdx=0;timeSlices.forEach(function(timeSlice){if(timeSlice.schedulingState==SCHEDULING_STATE.RUNNING){while(sliceIdx<this.topLevelSlices.length){if(this.addCpuTimeToSubslice_(this.topLevelSlices[sliceIdx],timeSlice)){sliceIdx++;}else{break;}}}},this);},addCpuTimeToSubslice_:function(slice,timeSlice){if(slice.start>timeSlice.end||slice.end<timeSlice.start)
+this.slices=slices;},addCpuTimeToSubslices_:function(timeSlices){var SCHEDULING_STATE=tr.model.SCHEDULING_STATE;var sliceIdx=0;timeSlices.forEach(function(timeSlice){if(timeSlice.schedulingState==SCHEDULING_STATE.RUNNING){while(sliceIdx<this.topLevelSlices.length){if(this.addCpuTimeToSubslice_(this.topLevelSlices[sliceIdx],timeSlice)){sliceIdx++;}else{break;}}}},this);},addCpuTimeToSubslice_:function(slice,timeSlice){if(slice.start>timeSlice.end||slice.end<timeSlice.start)
 return slice.end<=timeSlice.end;var duration=timeSlice.duration;if(slice.start>timeSlice.start)
 duration-=slice.start-timeSlice.start;if(timeSlice.end>slice.end)
 duration-=timeSlice.end-slice.end;if(slice.cpuDuration){slice.cpuDuration+=duration;}else{slice.cpuDuration=duration;}
 for(var i=0;i<slice.subSlices.length;i++){this.addCpuTimeToSubslice_(slice.subSlices[i],timeSlice);}
 return slice.end<=timeSlice.end;}};SliceGroup.merge=function(groupA,groupB){if(groupA.openPartialSlices_.length>0)
 throw new Error('groupA has open partial slices');if(groupB.openPartialSlices_.length>0)
-throw new Error('groupB has open partial slices');if(groupA.parentThread!=groupB.parentThread)
+throw new Error('groupB has open partial slices');if(groupA.parentContainer!=groupB.parentContainer)
 throw new Error('Different parent threads. Cannot merge');if(groupA.sliceConstructor!=groupB.sliceConstructor)
-throw new Error('Different slice constructors. Cannot merge');var result=new SliceGroup(groupA.parentThread,groupA.sliceConstructor,groupA.name_);var slicesA=groupA.slices;var slicesB=groupB.slices;var idxA=0;var idxB=0;var openA=[];var openB=[];var splitOpenSlices=function(when){for(var i=0;i<openB.length;i++){var oldSlice=openB[i];var oldEnd=oldSlice.end;if(when<oldSlice.start||oldEnd<when){throw new Error('slice should not be split');}
+throw new Error('Different slice constructors. Cannot merge');var result=new SliceGroup(groupA.parentContainer,groupA.sliceConstructor,groupA.name_);var slicesA=groupA.slices;var slicesB=groupB.slices;var idxA=0;var idxB=0;var openA=[];var openB=[];var splitOpenSlices=function(when){for(var i=0;i<openB.length;i++){var oldSlice=openB[i];var oldEnd=oldSlice.end;if(when<oldSlice.start||oldEnd<when){throw new Error('slice should not be split');}
 var newSlice=result.copySlice(oldSlice);newSlice.start=when;newSlice.duration=oldEnd-when;if(newSlice.title.indexOf(' (cont.)')==-1)
 newSlice.title+=' (cont.)';oldSlice.duration=when-oldSlice.start;openB[i]=newSlice;result.pushSlice(newSlice);}};var closeOpenSlices=function(upTo){while(openA.length>0||openB.length>0){var nextA=openA[openA.length-1];var nextB=openB[openB.length-1];var endA=nextA&&nextA.end;var endB=nextB&&nextB.end;if((endA===undefined||endA>upTo)&&(endB===undefined||endB>upTo)){return;}
 if(endB===undefined||endA<endB){splitOpenSlices(endA);openA.pop();}else{openB.pop();}}};while(idxA<slicesA.length||idxB<slicesB.length){var sA=slicesA[idxA];var sB=slicesB[idxB];var nextSlice,isFromB;if(sA===undefined||(sB!==undefined&&sA.start>sB.start)){nextSlice=result.copySlice(sB);isFromB=true;idxB++;}else{nextSlice=result.copySlice(sA);isFromB=false;idxA++;}
 closeOpenSlices(nextSlice.start);result.pushSlice(nextSlice);if(isFromB){openB.push(nextSlice);}else{splitOpenSlices(nextSlice.start);openA.push(nextSlice);}}
-closeOpenSlices();return result;};return{SliceGroup:SliceGroup};});'use strict';tv.exportTo('tv.c.trace_model',function(){function AsyncSlice(category,title,colorId,start,args,duration,opt_isTopLevel,opt_cpuStart,opt_cpuDuration){tv.c.trace_model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.startStackFrame=undefined;this.endStackFrame=undefined;this.didNotFinish=false;this.important=false;this.subSlices=[];this.id=undefined;this.startThread=undefined;this.endThread=undefined;this.cpuStart=undefined;this.cpuDuration=undefined;this.duration=duration;this.isTopLevel=(opt_isTopLevel===true);if(opt_cpuStart!==undefined)
+closeOpenSlices();return result;};return{SliceGroup:SliceGroup};});'use strict';tr.exportTo('tr.model',function(){function AsyncSlice(category,title,colorId,start,args,duration,opt_isTopLevel,opt_cpuStart,opt_cpuDuration){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.startStackFrame=undefined;this.endStackFrame=undefined;this.didNotFinish=false;this.important=false;this.subSlices=[];this.parentContainer=undefined;this.id=undefined;this.startThread=undefined;this.endThread=undefined;this.cpuStart=undefined;this.cpuDuration=undefined;this.duration=duration;this.isTopLevel=(opt_isTopLevel===true);if(opt_cpuStart!==undefined)
 this.cpuStart=opt_cpuStart;if(opt_cpuDuration!==undefined)
-this.cpuDuration=opt_cpuDuration;};AsyncSlice.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get viewSubGroupTitle(){return this.title;},get userFriendlyName(){return'Async slice '+this.title+' at '+
-tv.c.analysis.tsString(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices)
+this.cpuDuration=opt_cpuDuration;};AsyncSlice.prototype={__proto__:tr.model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get viewSubGroupTitle(){return this.title;},get userFriendlyName(){return'Async slice '+this.title+' at '+
+tr.b.units.tsString(this.start);},findDescendentSlice:function(targetTitle){if(!this.subSlices)
 return undefined;for(var i=0;i<this.subSlices.length;i++){if(this.subSlices[i].title==targetTitle)
 return this.subSlices[i];var slice=this.subSlices[i].findDescendentSlice(targetTitle);if(slice)return slice;}
-return undefined;},iterateAllDescendents:function(callback,opt_this){this.subSlices.forEach(callback,opt_this);this.subSlices.forEach(function(subSlice){subSlice.iterateAllDescendents(callback,opt_this);},opt_this);},compareTo:function(that){return this.title.localeCompare(that.title);}};tv.c.trace_model.EventRegistry.register(AsyncSlice,{name:'asyncSlice',pluralName:'asyncSlices',singleViewElementName:'tv-c-a-single-async-slice-sub-view',multiViewElementName:'tv-c-a-multi-async-slice-sub-view'});var options=new tv.b.ExtensionRegistryOptions(tv.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=AsyncSlice;options.defaultConstructor=AsyncSlice;tv.b.decorateExtensionRegistry(AsyncSlice,options);return{AsyncSlice:AsyncSlice};});'use strict';tv.exportTo('tv.c.trace_model',function(){function AsyncSliceGroup(parentThread,opt_name){this.parentThread_=parentThread;this.guid_=tv.b.GUID.allocate();this.slices=[];this.bounds=new tv.b.Range();this.name_=opt_name;this.viewSubGroups_=undefined;}
-AsyncSliceGroup.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,get guid(){return this.guid_;},get parentThread(){return this.parentThread_;},get model(){return this.parentThread_.parent.model;},get stableId(){return this.parentThread_.stableId+'.AsyncSliceGroup';},getSettingsKey:function(){if(!this.name_)
-return undefined;var parentKey=this.parentThread_.getSettingsKey();if(!parentKey)
-return undefined;return parentKey+'.'+this.name_;},push:function(slice){this.slices.push(slice);},get length(){return this.slices.length;},shiftTimestampsForward:function(amount){for(var sI=0;sI<this.slices.length;sI++){var slice=this.slices[sI];slice.start=(slice.start+amount);var shiftSubSlices=function(subSlices){if(subSlices===undefined||subSlices.length===0)
+return undefined;},iterateAllDescendents:function(callback,opt_this){this.subSlices.forEach(callback,opt_this);this.subSlices.forEach(function(subSlice){subSlice.iterateAllDescendents(callback,opt_this);},opt_this);},compareTo:function(that){return this.title.localeCompare(that.title);}};tr.model.EventRegistry.register(AsyncSlice,{name:'asyncSlice',pluralName:'asyncSlices',singleViewElementName:'tr-c-a-single-async-slice-sub-view',multiViewElementName:'tr-c-a-multi-async-slice-sub-view'});var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=AsyncSlice;options.defaultConstructor=AsyncSlice;tr.b.decorateExtensionRegistry(AsyncSlice,options);return{AsyncSlice:AsyncSlice};});'use strict';tr.exportTo('tr.model',function(){function AsyncSliceGroup(parentContainer,opt_name){this.parentContainer_=parentContainer;this.guid_=tr.b.GUID.allocate();this.slices=[];this.bounds=new tr.b.Range();this.name_=opt_name;this.viewSubGroups_=undefined;}
+AsyncSliceGroup.prototype={__proto__:tr.model.EventContainer.prototype,get guid(){return this.guid_;},get parentContainer(){return this.parentContainer_;},get model(){return this.parentContainer_.parent.model;},get stableId(){return this.parentContainer_.stableId+'.AsyncSliceGroup';},getSettingsKey:function(){if(!this.name_)
+return undefined;var parentKey=this.parentContainer_.getSettingsKey();if(!parentKey)
+return undefined;return parentKey+'.'+this.name_;},push:function(slice){slice.parentContainer=this.parentContainer;this.slices.push(slice);return slice;},get length(){return this.slices.length;},shiftTimestampsForward:function(amount){for(var sI=0;sI<this.slices.length;sI++){var slice=this.slices[sI];slice.start=(slice.start+amount);var shiftSubSlices=function(subSlices){if(subSlices===undefined||subSlices.length===0)
 return;for(var sJ=0;sJ<subSlices.length;sJ++){subSlices[sJ].start+=amount;shiftSubSlices(subSlices[sJ].subSlices);}};shiftSubSlices(slice.subSlices);}},updateBounds:function(){this.bounds.reset();for(var i=0;i<this.slices.length;i++){this.bounds.addValue(this.slices[i].start);this.bounds.addValue(this.slices[i].end);}},get viewSubGroups(){if(this.viewSubGroups_===undefined){var prefix='';if(this.name!==undefined)
 prefix=this.name+'.';else
-prefix='';var subGroupsByTitle={};for(var i=0;i<this.slices.length;++i){var slice=this.slices[i];var subGroupTitle=slice.viewSubGroupTitle;if(!subGroupsByTitle[subGroupTitle]){subGroupsByTitle[subGroupTitle]=new AsyncSliceGroup(this.parentThread_,prefix+subGroupTitle);}
-subGroupsByTitle[subGroupTitle].slices.push(slice);}
-this.viewSubGroups_=tv.b.dictionaryValues(subGroupsByTitle);this.viewSubGroups_.sort(function(a,b){return a.slices[0].compareTo(b.slices[0]);});}
-return this.viewSubGroups_;},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,tv.c.trace_model.AsyncSlice)){for(var i=0;i<this.slices.length;i++){var slice=this.slices[i];callback.call(opt_this,slice);if(slice.subSlices)
-slice.subSlices.forEach(callback,opt_this);}}},iterateAllChildEventContainers:function(callback,opt_this){}};return{AsyncSliceGroup:AsyncSliceGroup};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Slice=tv.c.trace_model.Slice;var SliceGroup=tv.c.trace_model.SliceGroup;var AsyncSlice=tv.c.trace_model.AsyncSlice;var AsyncSliceGroup=tv.c.trace_model.AsyncSliceGroup;var ThreadSlice=tv.c.trace_model.ThreadSlice;var ThreadTimeSlice=tv.c.trace_model.ThreadTimeSlice;function Thread(parent,tid){this.guid_=tv.b.GUID.allocate();if(!parent)
-throw new Error('Parent must be provided.');this.parent=parent;this.sortIndex=0;this.tid=tid;this.name=undefined;this.samples_=undefined;var that=this;function ThreadSliceForThisThread(cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration){ThreadSlice.call(this,cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration);this.parentThread=that;}
-ThreadSliceForThisThread.prototype={__proto__:ThreadSlice.prototype};this.sliceGroup=new SliceGroup(this,ThreadSliceForThisThread,'slices');this.timeSlices=undefined;this.kernelSliceGroup=new SliceGroup(this,ThreadSliceForThisThread,'kernel-slices');this.asyncSliceGroup=new AsyncSliceGroup(this,'async-slices');this.bounds=new tv.b.Range();}
-Thread.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,get guid(){return this.guid_;},get stableId(){return this.parent.stableId+'.'+this.tid;},compareTo:function(that){return Thread.compare(this,that);},iterateAllChildEventContainers:function(callback,opt_this){if(this.sliceGroup.length)
+prefix='';var subGroupsByTitle={};for(var i=0;i<this.slices.length;++i){var slice=this.slices[i];var subGroupTitle=slice.viewSubGroupTitle;if(!subGroupsByTitle[subGroupTitle]){subGroupsByTitle[subGroupTitle]=new AsyncSliceGroup(this.parentContainer_,prefix+subGroupTitle);}
+subGroupsByTitle[subGroupTitle].push(slice);}
+this.viewSubGroups_=tr.b.dictionaryValues(subGroupsByTitle);this.viewSubGroups_.sort(function(a,b){return a.slices[0].compareTo(b.slices[0]);});}
+return this.viewSubGroups_;},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,tr.model.AsyncSlice)){for(var i=0;i<this.slices.length;i++){var slice=this.slices[i];callback.call(opt_this,slice);if(slice.subSlices)
+slice.subSlices.forEach(callback,opt_this);}}},iterateAllChildEventContainers:function(callback,opt_this){}};return{AsyncSliceGroup:AsyncSliceGroup};});'use strict';tr.exportTo('tr.model',function(){var Slice=tr.model.Slice;var SliceGroup=tr.model.SliceGroup;var AsyncSlice=tr.model.AsyncSlice;var AsyncSliceGroup=tr.model.AsyncSliceGroup;var ThreadSlice=tr.model.ThreadSlice;var ThreadTimeSlice=tr.model.ThreadTimeSlice;function Thread(parent,tid){this.guid_=tr.b.GUID.allocate();if(!parent)
+throw new Error('Parent must be provided.');this.parent=parent;this.sortIndex=0;this.tid=tid;this.name=undefined;this.samples_=undefined;var that=this;this.sliceGroup=new SliceGroup(this,ThreadSlice,'slices');this.timeSlices=undefined;this.kernelSliceGroup=new SliceGroup(this,ThreadSlice,'kernel-slices');this.asyncSliceGroup=new AsyncSliceGroup(this,'async-slices');this.bounds=new tr.b.Range();}
+Thread.prototype={__proto__:tr.model.EventContainer.prototype,get guid(){return this.guid_;},get stableId(){return this.parent.stableId+'.'+this.tid;},compareTo:function(that){return Thread.compare(this,that);},iterateAllChildEventContainers:function(callback,opt_this){if(this.sliceGroup.length)
 callback.call(opt_this,this.sliceGroup);if(this.kernelSliceGroup.length)
 callback.call(opt_this,this.kernelSliceGroup);if(this.asyncSliceGroup.length)
 callback.call(opt_this,this.asyncSliceGroup);},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(this.timeSlices&&this.timeSlices.length){if(eventTypePredicate.call(opt_this,ThreadTimeSlice))
@@ -2322,18 +2314,18 @@
 categoriesDict[this.samples_[i].category]=true;}},autoCloseOpenSlices:function(opt_maxTimestamp){this.sliceGroup.autoCloseOpenSlices(opt_maxTimestamp);this.kernelSliceGroup.autoCloseOpenSlices(opt_maxTimestamp);},mergeKernelWithUserland:function(){if(this.kernelSliceGroup.length>0){var newSlices=SliceGroup.merge(this.sliceGroup,this.kernelSliceGroup);this.sliceGroup.slices=newSlices.slices;this.kernelSliceGroup=new SliceGroup(this);this.updateBounds();}},createSubSlices:function(){this.sliceGroup.createSubSlices();this.samples_=this.parent.model.samples.filter(function(sample){return sample.thread==this;},this);},get userFriendlyName(){return this.name||this.tid;},get userFriendlyDetails(){return'tid: '+this.tid+
 (this.name?', name: '+this.name:'');},getSettingsKey:function(){if(!this.name)
 return undefined;var parentKey=this.parent.getSettingsKey();if(!parentKey)
-return undefined;return parentKey+'.'+this.name;},indexOfTimeSlice:function(timeSlice){var i=tv.b.findLowIndexInSortedArray(this.timeSlices,function(slice){return slice.start;},timeSlice.start);if(this.timeSlices[i]!==timeSlice)
+return undefined;return parentKey+'.'+this.name;},indexOfTimeSlice:function(timeSlice){var i=tr.b.findLowIndexInSortedArray(this.timeSlices,function(slice){return slice.start;},timeSlice.start);if(this.timeSlices[i]!==timeSlice)
 return undefined;return i;},getSchedulingStatsForRange:function(start,end){var stats={};if(!this.timeSlices)return stats;function addStatsForSlice(threadTimeSlice){var overlapStart=Math.max(threadTimeSlice.start,start);var overlapEnd=Math.min(threadTimeSlice.end,end);var schedulingState=threadTimeSlice.schedulingState;if(!(schedulingState in stats))
 stats[schedulingState]=0;stats[schedulingState]+=overlapEnd-overlapStart;}
-tv.b.iterateOverIntersectingIntervals(this.timeSlices,function(x){return x.start;},function(x){return x.end;},start,end,addStatsForSlice);return stats;},get samples(){return this.samples_;}};Thread.compare=function(x,y){var tmp=x.parent.compareTo(y.parent);if(tmp)
+tr.b.iterateOverIntersectingIntervals(this.timeSlices,function(x){return x.start;},function(x){return x.end;},start,end,addStatsForSlice);return stats;},get samples(){return this.samples_;}};Thread.compare=function(x,y){var tmp=x.parent.compareTo(y.parent);if(tmp)
 return tmp;tmp=x.sortIndex-y.sortIndex;if(tmp)
-return tmp;tmp=tv.b.comparePossiblyUndefinedValues(x.name,y.name,function(x,y){return x.localeCompare(y);});if(tmp)
-return tmp;return x.tid-y.tid;};return{Thread:Thread};});'use strict';tv.exportTo('tv.c',function(){var Settings=tv.b.Settings;function TraceModelSettings(model){this.model=model;this.objectsByKey_=[];this.nonuniqueKeys_=[];this.buildObjectsByKeyMap_();this.removeNonuniqueKeysFromSettings_();this.ephemeralSettingsByGUID_={};}
-TraceModelSettings.prototype={buildObjectsByKeyMap_:function(){var objects=[];this.model.iterateAllPersistableObjects(function(o){objects.push(o);});var objectsByKey={};var NONUNIQUE_KEY='nonuniqueKey';for(var i=0;i<objects.length;i++){var object=objects[i];var objectKey=object.getSettingsKey();if(!objectKey)
+return tmp;tmp=tr.b.comparePossiblyUndefinedValues(x.name,y.name,function(x,y){return x.localeCompare(y);});if(tmp)
+return tmp;return x.tid-y.tid;};return{Thread:Thread};});'use strict';tr.exportTo('tr.model',function(){var Settings=tr.b.Settings;function ModelSettings(model){this.model=model;this.objectsByKey_=[];this.nonuniqueKeys_=[];this.buildObjectsByKeyMap_();this.removeNonuniqueKeysFromSettings_();this.ephemeralSettingsByGUID_={};}
+ModelSettings.prototype={buildObjectsByKeyMap_:function(){var objects=[];this.model.iterateAllPersistableObjects(function(o){objects.push(o);});var objectsByKey={};var NONUNIQUE_KEY='nonuniqueKey';for(var i=0;i<objects.length;i++){var object=objects[i];var objectKey=object.getSettingsKey();if(!objectKey)
 continue;if(objectsByKey[objectKey]===undefined){objectsByKey[objectKey]=object;continue;}
 objectsByKey[objectKey]=NONUNIQUE_KEY;}
-var nonuniqueKeys={};tv.b.dictionaryKeys(objectsByKey).forEach(function(objectKey){if(objectsByKey[objectKey]!==NONUNIQUE_KEY)
-return;delete objectsByKey[objectKey];nonuniqueKeys[objectKey]=true;});this.nonuniqueKeys=nonuniqueKeys;this.objectsByKey_=objectsByKey;},removeNonuniqueKeysFromSettings_:function(){var settings=Settings.get('trace_model_settings',{});var settingsChanged=false;tv.b.dictionaryKeys(settings).forEach(function(objectKey){if(!this.nonuniqueKeys[objectKey])
+var nonuniqueKeys={};tr.b.dictionaryKeys(objectsByKey).forEach(function(objectKey){if(objectsByKey[objectKey]!==NONUNIQUE_KEY)
+return;delete objectsByKey[objectKey];nonuniqueKeys[objectKey]=true;});this.nonuniqueKeys=nonuniqueKeys;this.objectsByKey_=objectsByKey;},removeNonuniqueKeysFromSettings_:function(){var settings=Settings.get('trace_model_settings',{});var settingsChanged=false;tr.b.dictionaryKeys(settings).forEach(function(objectKey){if(!this.nonuniqueKeys[objectKey])
 return;settingsChanged=true;delete settings[objectKey];},this);if(settingsChanged)
 Settings.set('trace_model_settings',settings);},hasUniqueSettingKey:function(object){var objectKey=object.getSettingsKey();if(!objectKey)
 return false;return this.objectsByKey_[objectKey]!==undefined;},getSettingFor:function(object,objectLevelKey,defaultValue){var objectKey=object.getSettingsKey();if(!objectKey||!this.objectsByKey_[objectKey]){var settings=this.getEphemeralSettingsFor_(object);var ephemeralValue=settings[objectLevelKey];if(ephemeralValue!==undefined)
@@ -2345,8 +2337,8 @@
 settings[objectKey]={};if(settings[objectKey][objectLevelKey]===value)
 return;settings[objectKey][objectLevelKey]=value;Settings.set('trace_model_settings',settings);},getEphemeralSettingsFor_:function(object){if(object.guid===undefined)
 throw new Error('Only objects with GUIDs can be persisted');if(this.ephemeralSettingsByGUID_[object.guid]===undefined)
-this.ephemeralSettingsByGUID_[object.guid]={};return this.ephemeralSettingsByGUID_[object.guid];}};return{TraceModelSettings:TraceModelSettings};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Thread=tv.c.trace_model.Thread;var Counter=tv.c.trace_model.Counter;function ProcessBase(model){if(!model)
-throw new Error('Must provide a model');tv.c.trace_model.EventContainer.call(this,model);this.guid_=tv.b.GUID.allocate();this.model=model;this.threads={};this.counters={};this.objects=new tv.c.trace_model.ObjectCollection(this);this.bounds=new tv.b.Range();this.sortIndex=0;};ProcessBase.compare=function(x,y){return x.sortIndex-y.sortIndex;};ProcessBase.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,get guid(){return this.guid_;},get stableId(){throw new Error('Not implemented');},iterateAllChildEventContainers:function(callback,opt_this){for(var tid in this.threads)
+this.ephemeralSettingsByGUID_[object.guid]={};return this.ephemeralSettingsByGUID_[object.guid];}};return{ModelSettings:ModelSettings};});'use strict';tr.exportTo('tr.model',function(){var Thread=tr.model.Thread;var Counter=tr.model.Counter;function ProcessBase(model){if(!model)
+throw new Error('Must provide a model');tr.model.EventContainer.call(this);this.guid_=tr.b.GUID.allocate();this.model=model;this.threads={};this.counters={};this.objects=new tr.model.ObjectCollection(this);this.bounds=new tr.b.Range();this.sortIndex=0;};ProcessBase.compare=function(x,y){return x.sortIndex-y.sortIndex;};ProcessBase.prototype={__proto__:tr.model.EventContainer.prototype,get guid(){return this.guid_;},get stableId(){throw new Error('Not implemented');},iterateAllChildEventContainers:function(callback,opt_this){for(var tid in this.threads)
 callback.call(opt_this,this.threads[tid]);for(var id in this.counters)
 callback.call(opt_this,this.counters[id]);callback.call(opt_this,this.objects);},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){},iterateAllPersistableObjects:function(cb){cb(this);for(var tid in this.threads)
 this.threads[tid].iterateAllPersistableObjects(cb);},get numThreads(){var n=0;for(var p in this.threads){n++;}
@@ -2366,26 +2358,61 @@
 this.threads=threadsToKeep;},getThread:function(tid){return this.threads[tid];},getOrCreateThread:function(tid){if(!this.threads[tid])
 this.threads[tid]=new Thread(this,tid);return this.threads[tid];},getOrCreateCounter:function(cat,name){var id=cat+'.'+name;if(!this.counters[id])
 this.counters[id]=new Counter(this,id,cat,name);return this.counters[id];},getSettingsKey:function(){throw new Error('Not implemented');},createSubSlices:function(){for(var tid in this.threads)
-this.threads[tid].createSubSlices();}};return{ProcessBase:ProcessBase};});'use strict';tv.exportTo('tv.c.trace_model',function(){var Cpu=tv.c.trace_model.Cpu;var ProcessBase=tv.c.trace_model.ProcessBase;function Kernel(model){if(model===undefined)
-throw new Error('model must be provided');ProcessBase.call(this,model);this.cpus={};this.softwareMeasuredCpuCount_=undefined;};Kernel.compare=function(x,y){return 0;};Kernel.prototype={__proto__:ProcessBase.prototype,compareTo:function(that){return Kernel.compare(this,that);},get userFriendlyName(){return'Kernel';},get userFriendlyDetails(){return'Kernel';},get stableId(){return'Kernel';},getOrCreateCpu:function(cpuNumber){if(!this.cpus[cpuNumber])
+this.threads[tid].createSubSlices();}};return{ProcessBase:ProcessBase};});'use strict';tr.exportTo('tr.model',function(){var Cpu=tr.model.Cpu;var ProcessBase=tr.model.ProcessBase;function Kernel(model){ProcessBase.call(this,model);this.cpus={};this.softwareMeasuredCpuCount_=undefined;};Kernel.compare=function(x,y){return 0;};Kernel.prototype={__proto__:ProcessBase.prototype,compareTo:function(that){return Kernel.compare(this,that);},get userFriendlyName(){return'Kernel';},get userFriendlyDetails(){return'Kernel';},get stableId(){return'Kernel';},getOrCreateCpu:function(cpuNumber){if(!this.cpus[cpuNumber])
 this.cpus[cpuNumber]=new Cpu(this,cpuNumber);return this.cpus[cpuNumber];},get softwareMeasuredCpuCount(){return this.softwareMeasuredCpuCount_;},set softwareMeasuredCpuCount(softwareMeasuredCpuCount){if(this.softwareMeasuredCpuCount_!==undefined&&this.softwareMeasuredCpuCount_!==softwareMeasuredCpuCount){throw new Error('Cannot change the softwareMeasuredCpuCount once it is set');}
-this.softwareMeasuredCpuCount_=softwareMeasuredCpuCount;},get bestGuessAtCpuCount(){var realCpuCount=tv.b.dictionaryLength(this.cpus);if(realCpuCount!==0)
+this.softwareMeasuredCpuCount_=softwareMeasuredCpuCount;},get bestGuessAtCpuCount(){var realCpuCount=tr.b.dictionaryLength(this.cpus);if(realCpuCount!==0)
 return realCpuCount;return this.softwareMeasuredCpuCount;},shiftTimestampsForward:function(amount){ProcessBase.prototype.shiftTimestampsForward.call(this,amount);for(var cpuNumber in this.cpus)
 this.cpus[cpuNumber].shiftTimestampsForward(amount);},updateBounds:function(){ProcessBase.prototype.updateBounds.call(this);for(var cpuNumber in this.cpus){var cpu=this.cpus[cpuNumber];cpu.updateBounds();this.bounds.addRange(cpu.bounds);}},createSubSlices:function(){ProcessBase.prototype.createSubSlices.call(this);for(var cpuNumber in this.cpus){var cpu=this.cpus[cpuNumber];cpu.createSubSlices();}},addCategoriesToDict:function(categoriesDict){ProcessBase.prototype.addCategoriesToDict.call(this,categoriesDict);for(var cpuNumber in this.cpus)
 this.cpus[cpuNumber].addCategoriesToDict(categoriesDict);},getSettingsKey:function(){return'kernel';},iterateAllChildEventContainers:function(callback,opt_this){ProcessBase.prototype.iterateAllChildEventContainers.call(this,callback,opt_this);for(var cpuId in this.cpus)
-callback.call(opt_this,this.cpus[cpuId]);},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){ProcessBase.prototype.iterateAllEventsInThisContainer.call(this,eventTypePredicate,callback,opt_this);}};return{Kernel:Kernel};});'use strict';tv.exportTo('tv.c.trace_model',function(){function ContainerMemoryDump(start){tv.c.trace_model.TimedEvent.call(this,start);this.memoryAllocatorDumps_=undefined;this.memoryAllocatorDumpsByFullName_=undefined;};ContainerMemoryDump.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype,shiftTimestampsForward:function(amount){this.start+=amount;},get memoryAllocatorDumps(){return this.memoryAllocatorDumps_;},set memoryAllocatorDumps(memoryAllocatorDumps){this.memoryAllocatorDumps_=memoryAllocatorDumps;this.memoryAllocatorDumpsByFullName_=undefined;},getMemoryAllocatorDumpByFullName:function(fullName){if(this.memoryAllocatorDumps_===undefined)
+callback.call(opt_this,this.cpus[cpuId]);},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){ProcessBase.prototype.iterateAllEventsInThisContainer.call(this,eventTypePredicate,callback,opt_this);}};return{Kernel:Kernel};});'use strict';tr.exportTo('tr.model',function(){function Attribute(units){this.units=units;}
+Attribute.fromDictIfPossible=function(dict,opt_model){var typeInfo=Attribute.findTypeInfoMatching(function(typeInfo){return typeInfo.metadata.type===dict.type;});if(typeInfo===undefined){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Unknown attribute type \''+dict.type+'\'.'});}
+return UnknownAttribute.fromDict(dict,opt_model);}
+return typeInfo.constructor.fromDict(dict,opt_model);};Attribute.findCommonTraits=function(attributes,opt_model){var commonTraits;for(var i=0;i<attributes.length;i++){var attribute=attributes[i];if(attribute===undefined)
+continue;var attributeConstructor=attribute.constructor;var attributeUnits=attribute.units;if(commonTraits===undefined){commonTraits={constructor:attributeConstructor,units:attributeUnits};}else if(attributeConstructor!==commonTraits.constructor){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different types: '+
+commonTraits.constructor+' and '+attributeConstructor+'.'});}
+commonTraits={constructor:UnknownAttribute,units:undefined};break;}else if(attributeUnits!==commonTraits.units){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different units: '+commonTraits.units+' and '+attributeUnits+'.'});}
+commonTraits={constructor:UnknownAttribute,units:undefined};break;}}
+return commonTraits;};Attribute.aggregate=function(childAttributes,existingParentAttribute,opt_model){var definedChildAttributes=childAttributes.filter(function(childAttribute){return childAttribute!==undefined;});var traits=Attribute.findCommonTraits(definedChildAttributes,opt_model);if(traits===undefined)
+return existingParentAttribute;var constructor=traits.constructor;if(constructor.merge===undefined)
+return existingParentAttribute;var mergedAttribute=constructor.merge(definedChildAttributes,traits.units,opt_model);if(existingParentAttribute===undefined)
+return mergedAttribute;existingParentAttribute.useMergedAttribute(mergedAttribute,opt_model);return existingParentAttribute;}
+Attribute.fromTraceValue=function(dict,opt_model){throw new Error('Not implemented');};Attribute.prototype.useMergedAttribute=function(mergedAttribute,opt_model){if(mergedAttribute.constructor!==this.constructor){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different types: '+this.constructor+' and '+mergedAttribute.constructor+'.'});}}else if(mergedAttribute.units!==this.units){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different units: '+this.units+' and '+mergedAttribute.units+'.'});}}};var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.mandatoryBaseType=Attribute;tr.b.decorateExtensionRegistry(Attribute,options);Attribute.addEventListener('will-register',function(e){if(!e.typeInfo.constructor.hasOwnProperty('fromDict'))
+throw new Error('Attributes must have fromDict method');if(!e.typeInfo.metadata.type)
+throw new Error('Attributes must provide type');if(e.typeInfo.constructor.prototype.constructor!==e.typeInfo.constructor)
+throw new Error('Attribute prototypes must provide constructor.');});function ScalarAttribute(units,value){Attribute.call(this,units);this.value=value;}
+ScalarAttribute.fromDict=function(dict){return new ScalarAttribute(dict.units,parseInt(dict.value,16));};ScalarAttribute.merge=function(childAttributes,units){var sum=0;childAttributes.forEach(function(childAttribute){sum+=childAttribute.value;});return new ScalarAttribute(units,sum);}
+ScalarAttribute.prototype.__proto__=Attribute.prototype;Attribute.register(ScalarAttribute,{type:'scalar'});function StringAttribute(units,value){Attribute.call(this,units);this.value=value;}
+StringAttribute.fromDict=function(dict){return new StringAttribute(dict.units,dict.value);};Attribute.register(StringAttribute,{type:'string'});function UnknownAttribute(units,opt_value){Attribute.call(this,units,opt_value);this.value=opt_value;}
+UnknownAttribute.fromDict=function(dict){return new UnknownAttribute(dict.units);};UnknownAttribute.prototype.__proto__=Attribute.prototype;return{Attribute:Attribute,ScalarAttribute:ScalarAttribute,StringAttribute:StringAttribute,UnknownAttribute:UnknownAttribute};});'use strict';tr.exportTo('tr.model',function(){function ContainerMemoryDump(start){tr.model.TimedEvent.call(this,start);this.memoryAllocatorDumps_=undefined;this.memoryAllocatorDumpsByFullName_=undefined;};ContainerMemoryDump.prototype={__proto__:tr.model.TimedEvent.prototype,shiftTimestampsForward:function(amount){this.start+=amount;},get memoryAllocatorDumps(){return this.memoryAllocatorDumps_;},set memoryAllocatorDumps(memoryAllocatorDumps){this.memoryAllocatorDumps_=memoryAllocatorDumps;this.memoryAllocatorDumpsByFullName_=undefined;},getMemoryAllocatorDumpByFullName:function(fullName){if(this.memoryAllocatorDumps_===undefined)
 return undefined;if(this.memoryAllocatorDumpsByFullName_===undefined){var index={};function addDumpsToIndex(dumps){dumps.forEach(function(dump){index[dump.fullName]=dump;addDumpsToIndex(dump.children);});};addDumpsToIndex(this.memoryAllocatorDumps_);this.memoryAllocatorDumpsByFullName_=index;}
-return this.memoryAllocatorDumpsByFullName_[fullName];}};return{ContainerMemoryDump:ContainerMemoryDump};});'use strict';tv.exportTo('tv.c.trace_model',function(){function ProcessMemoryDump(globalMemoryDump,process,start){tv.c.trace_model.ContainerMemoryDump.call(this,start);this.process=process;this.globalMemoryDump=globalMemoryDump;this.totalResidentBytes=undefined;this.vmRegions_=undefined;};ProcessMemoryDump.prototype={__proto__:tv.c.trace_model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Process memory dump at '+tv.c.analysis.tsString(this.start);},get vmRegions(){throw new Error('VM regions must be accessed through the mostRecentVmRegions field');},set vmRegions(vmRegions){this.vmRegions_=vmRegions;},getMostRecentTotalVmRegionStat_:function(statGetterFn){if(this.mostRecentVmRegions===undefined)
-return undefined;var total=0;this.mostRecentVmRegions.forEach(function(vmRegion){total+=statGetterFn(vmRegion);});return total;},get mostRecentTotalProportionalResidentSizeInBytes(){return this.getMostRecentTotalVmRegionStat_(function(vmRegion){return vmRegion.byteStats.proportionalResident;});},get mostRecentTotalPrivateResidentSizeInBytes(){return this.getMostRecentTotalVmRegionStat_(function(vmRegion){return vmRegion.byteStats.privateResident;});},get mostRecentTotalSharedResidentSizeInBytes(){return this.getMostRecentTotalVmRegionStat_(function(vmRegion){return vmRegion.byteStats.sharedResident;});}};ProcessMemoryDump.hookUpMostRecentVmRegionsLinks=function(processDumps){var mostRecentVmRegions=undefined;processDumps.forEach(function(processDump){if(processDump.vmRegions_!==undefined)
+return this.memoryAllocatorDumpsByFullName_[fullName];},aggregateMemoryAllocatorDumpAttributes:function(opt_model){if(this.memoryAllocatorDumps_===undefined)
+return;this.memoryAllocatorDumps_.forEach(function(dump){dump.aggregateAttributes(opt_model);});}};return{ContainerMemoryDump:ContainerMemoryDump};});'use strict';tr.exportTo('tr.model',function(){function MemoryAllocatorDump(containerMemoryDump,fullName,opt_guid){this.fullName=fullName;this.parent=undefined;this.children=[];this.attributes={};this.containerMemoryDump=containerMemoryDump;this.owns=undefined;this.ownedBy=[];this.retains=[];this.retainedBy=[];this.guid=opt_guid;};MemoryAllocatorDump.prototype={get name(){return this.fullName.substring(this.fullName.lastIndexOf('/')+1);},addAttribute:function(name,value){if(name in this.attributes)
+throw new Error('Duplicate attribute name: '+name+'.');this.attributes[name]=value;},aggregateAttributes:function(opt_model){var attributes={};this.children.forEach(function(child){child.aggregateAttributes(opt_model);tr.b.iterItems(child.attributes,function(name){attributes[name]=true;},this);},this);tr.b.iterItems(attributes,function(name){var childAttributes=this.children.map(function(child){return child.attributes[name];},this);var currentAttribute=this.attributes[name];this.attributes[name]=tr.model.Attribute.aggregate(childAttributes,currentAttribute,opt_model);},this);}};function MemoryAllocatorDumpLink(source,target,opt_importance){this.source=source;this.target=target;this.importance=opt_importance;}
+return{MemoryAllocatorDump:MemoryAllocatorDump,MemoryAllocatorDumpLink:MemoryAllocatorDumpLink};});'use strict';tr.exportTo('tr.model',function(){function getValidSizeAttributeOrUndefined(memoryAllocatorDump,opt_model){var sizeAttr=memoryAllocatorDump.attributes['size'];if(sizeAttr===undefined)
+return undefined;if(!(sizeAttr instanceof tr.model.ScalarAttribute)){if(opt_model!==undefined){opt_model.importWarning({type:'memory_dump_parse_error',message:'\'size\' attribute of memory allocator dump \''+
+memoryAllocatorDump.fullName+'\' is not a scalar.'});}
+return undefined;}
+return sizeAttr;}
+function ProcessMemoryDump(globalMemoryDump,process,start){tr.model.ContainerMemoryDump.call(this,start);this.process=process;this.globalMemoryDump=globalMemoryDump;this.totalResidentBytes=undefined;this.vmRegions_=undefined;this.tracingMemoryDiscounted_=false;};ProcessMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Process memory dump at '+tr.b.units.tsString(this.start);},get vmRegions(){throw new Error('VM regions must be accessed through the mostRecentVmRegions field');},set vmRegions(vmRegions){this.vmRegions_=vmRegions;},getMostRecentTotalVmRegionStat:function(statName){if(this.mostRecentVmRegions===undefined)
+return undefined;var total=0;this.mostRecentVmRegions.forEach(function(vmRegion){var statValue=vmRegion.byteStats[statName];if(statValue===undefined)
+return;total+=statValue;});return total;},discountTracingOverhead:function(opt_model){if(this.tracingMemoryDiscounted_)
+return;this.tracingMemoryDiscounted_=true;var tracingDump=this.getMemoryAllocatorDumpByFullName('tracing');if(tracingDump===undefined)
+return;var tracingSizeAttr=getValidSizeAttributeOrUndefined(tracingDump,opt_model);if(tracingSizeAttr===undefined)
+return;var tracingSize=tracingSizeAttr.value;if(this.totalResidentBytes!==undefined)
+this.totalResidentBytes-=tracingSize;if(this.vmRegions_!==undefined){this.vmRegions_.push(VMRegion.fromDict({mappedFile:'[discounted tracing overhead]',byteStats:{privateDirtyResident:-tracingSize,proportionalResident:-tracingSize}}));}
+var mallocDump=this.getMemoryAllocatorDumpByFullName('malloc');if(mallocDump!==undefined){var overheadSizeAttribute=new tr.model.ScalarAttribute('bytes',-tracingSize);var overheadDump=new tr.model.MemoryAllocatorDump(this,'malloc/discounted_tracing_overhead');overheadDump.parent=mallocDump;overheadDump.addAttribute('size',overheadSizeAttribute);mallocDump.children.push(overheadDump);var mallocDumpSizeAttr=getValidSizeAttributeOrUndefined(mallocDump,opt_model);if(mallocDumpSizeAttr!==undefined)
+mallocDumpSizeAttr.value-=tracingSize;this.memoryAllocatorDumps=this.memoryAllocatorDumps;}}};ProcessMemoryDump.hookUpMostRecentVmRegionsLinks=function(processDumps){var mostRecentVmRegions=undefined;processDumps.forEach(function(processDump){if(processDump.vmRegions_!==undefined)
 mostRecentVmRegions=processDump.vmRegions_;processDump.mostRecentVmRegions=mostRecentVmRegions;});};function VMRegion(startAddress,sizeInBytes,protectionFlags,mappedFile,byteStats){this.startAddress=startAddress;this.sizeInBytes=sizeInBytes;this.protectionFlags=protectionFlags;this.mappedFile=mappedFile;this.byteStats=byteStats;};VMRegion.PROTECTION_FLAG_READ=4;VMRegion.PROTECTION_FLAG_WRITE=2;VMRegion.PROTECTION_FLAG_EXECUTE=1;VMRegion.prototype={get protectionFlagsToString(){if(this.protectionFlags===undefined)
 return undefined;return((this.protectionFlags&VMRegion.PROTECTION_FLAG_READ?'r':'-')+
 (this.protectionFlags&VMRegion.PROTECTION_FLAG_WRITE?'w':'-')+
-(this.protectionFlags&VMRegion.PROTECTION_FLAG_EXECUTE?'x':'-'));}};VMRegion.fromDict=function(dict){return new VMRegion(dict.startAddress,dict.sizeInBytes,dict.protectionFlags,dict.mappedFile,VMRegionByteStats.fromDict(dict.byteStats));};function VMRegionByteStats(privateResident,sharedResident,proportionalResident){this.privateResident=privateResident;this.sharedResident=sharedResident;this.proportionalResident=proportionalResident;};VMRegionByteStats.prototype={get totalResident(){return this.privateResident+this.sharedResident;}};VMRegionByteStats.fromDict=function(dict){return new VMRegionByteStats(dict.privateResident,dict.sharedResident,dict.proportionalResident);};tv.c.trace_model.EventRegistry.register(ProcessMemoryDump,{name:'processMemoryDump',pluralName:'processMemoryDumps',singleViewElementName:'tv-c-single-process-memory-dump-sub-view',multiViewElementName:'tv-c-multi-process-memory-dump-sub-view'});return{ProcessMemoryDump:ProcessMemoryDump,VMRegion:VMRegion,VMRegionByteStats:VMRegionByteStats};});'use strict';tv.exportTo('tv.c.trace_model',function(){var ProcessBase=tv.c.trace_model.ProcessBase;var ProcessInstantEvent=tv.c.trace_model.ProcessInstantEvent;var Frame=tv.c.trace_model.Frame;var ProcessMemoryDump=tv.c.trace_model.ProcessMemoryDump;function Process(model,pid){if(model===undefined)
+(this.protectionFlags&VMRegion.PROTECTION_FLAG_EXECUTE?'x':'-'));}};VMRegion.fromDict=function(dict){return new VMRegion(dict.startAddress,dict.sizeInBytes,dict.protectionFlags,dict.mappedFile,VMRegionByteStats.fromDict(dict.byteStats));};function VMRegionByteStats(privateCleanResident,privateDirtyResident,sharedCleanResident,sharedDirtyResident,proportionalResident,swapped){this.privateCleanResident=privateCleanResident;this.privateDirtyResident=privateDirtyResident;this.sharedCleanResident=sharedCleanResident;this.sharedDirtyResident=sharedDirtyResident;this.proportionalResident=proportionalResident;this.swapped=swapped;}
+VMRegionByteStats.fromDict=function(dict){return new VMRegionByteStats(dict.privateCleanResident,dict.privateDirtyResident,dict.sharedCleanResident,dict.sharedDirtyResident,dict.proportionalResident,dict.swapped);}
+tr.model.EventRegistry.register(ProcessMemoryDump,{name:'processMemoryDump',pluralName:'processMemoryDumps',singleViewElementName:'tr-c-a-single-process-memory-dump-sub-view',multiViewElementName:'tr-c-a-multi-process-memory-dump-sub-view'});return{ProcessMemoryDump:ProcessMemoryDump,VMRegion:VMRegion,VMRegionByteStats:VMRegionByteStats};});'use strict';tr.exportTo('tr.model',function(){var ProcessBase=tr.model.ProcessBase;var ProcessInstantEvent=tr.model.ProcessInstantEvent;var Frame=tr.model.Frame;var ProcessMemoryDump=tr.model.ProcessMemoryDump;function Process(model,pid){if(model===undefined)
 throw new Error('model must be provided');if(pid===undefined)
-throw new Error('pid must be provided');tv.c.trace_model.ProcessBase.call(this,model);this.pid=pid;this.name=undefined;this.labels=[];this.instantEvents=[];this.memoryDumps=[];this.frames=[];};Process.compare=function(x,y){var tmp=tv.c.trace_model.ProcessBase.compare(x,y);if(tmp)
-return tmp;tmp=tv.b.comparePossiblyUndefinedValues(x.name,y.name,function(x,y){return x.localeCompare(y);});if(tmp)
-return tmp;tmp=tv.b.compareArrays(x.labels,y.labels,function(x,y){return x.localeCompare(y);});if(tmp)
-return tmp;return x.pid-y.pid;};Process.prototype={__proto__:tv.c.trace_model.ProcessBase.prototype,get stableId(){return this.pid;},compareTo:function(that){return Process.compare(this,that);},iterateAllChildEventContainers:function(callback,opt_this){ProcessBase.prototype.iterateAllChildEventContainers.call(this,callback,opt_this);},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){ProcessBase.prototype.iterateAllEventsInThisContainer.call(this,eventTypePredicate,callback,opt_this);if(eventTypePredicate.call(opt_this,ProcessInstantEvent))
+throw new Error('pid must be provided');tr.model.ProcessBase.call(this,model);this.pid=pid;this.name=undefined;this.labels=[];this.instantEvents=[];this.memoryDumps=[];this.frames=[];};Process.compare=function(x,y){var tmp=tr.model.ProcessBase.compare(x,y);if(tmp)
+return tmp;tmp=tr.b.comparePossiblyUndefinedValues(x.name,y.name,function(x,y){return x.localeCompare(y);});if(tmp)
+return tmp;tmp=tr.b.compareArrays(x.labels,y.labels,function(x,y){return x.localeCompare(y);});if(tmp)
+return tmp;return x.pid-y.pid;};Process.prototype={__proto__:tr.model.ProcessBase.prototype,get stableId(){return this.pid;},compareTo:function(that){return Process.compare(this,that);},iterateAllChildEventContainers:function(callback,opt_this){ProcessBase.prototype.iterateAllChildEventContainers.call(this,callback,opt_this);},iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){ProcessBase.prototype.iterateAllEventsInThisContainer.call(this,eventTypePredicate,callback,opt_this);if(eventTypePredicate.call(opt_this,ProcessInstantEvent))
 this.instantEvents.forEach(callback,opt_this);if(eventTypePredicate.call(opt_this,Frame))
 this.frames.forEach(callback,opt_this);if(eventTypePredicate.call(opt_this,ProcessMemoryDump))
 this.memoryDumps.forEach(callback,opt_this);},pushInstantEvent:function(instantEvent){this.instantEvents.push(instantEvent);},addLabelIfNeeded:function(labelName){for(var i=0;i<this.labels.length;i++){if(this.labels[i]===labelName)
@@ -2399,11 +2426,11 @@
 return'processes.'+this.name;return'processes.'+this.name+'.'+this.labels.join('.');},shiftTimestampsForward:function(amount){for(var id in this.instantEvents)
 this.instantEvents[id].start+=amount;for(var i=0;i<this.frames.length;i++)
 this.frames[i].shiftTimestampsForward(amount);for(var i=0;i<this.memoryDumps.length;i++)
-this.memoryDumps[i].shiftTimestampsForward(amount);tv.c.trace_model.ProcessBase.prototype.shiftTimestampsForward.apply(this,arguments);},updateBounds:function(){tv.c.trace_model.ProcessBase.prototype.updateBounds.apply(this);for(var i=0;i<this.frames.length;i++)
+this.memoryDumps[i].shiftTimestampsForward(amount);tr.model.ProcessBase.prototype.shiftTimestampsForward.apply(this,arguments);},updateBounds:function(){tr.model.ProcessBase.prototype.updateBounds.apply(this);for(var i=0;i<this.frames.length;i++)
 this.frames[i].addBoundsToRange(this.bounds);for(var i=0;i<this.memoryDumps.length;i++)
-this.memoryDumps[i].addBoundsToRange(this.bounds);},finalizeMemoryDumps:function(){this.memoryDumps.sort(function(x,y){return x.start-y.start;});tv.c.trace_model.ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(this.memoryDumps);}};return{Process:Process};});'use strict';tv.exportTo('tv.c.trace_model',function(){function Sample(cpu,thread,title,start,leafStackFrame,opt_weight,opt_args){tv.c.trace_model.TimedEvent.call(this,start);this.title=title;this.cpu=cpu;this.thread=thread;this.leafStackFrame=leafStackFrame;this.weight=opt_weight;this.args=opt_args||{};}
-Sample.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype,get colorId(){return this.leafStackFrame.colorId;},get stackTrace(){return this.leafStackFrame.stackTrace;},getUserFriendlyStackTrace:function(){return this.leafStackFrame.getUserFriendlyStackTrace();},get userFriendlyName(){return'Sample '+' at '+
-tv.c.analysis.tsString(this.start);}};tv.c.trace_model.EventRegistry.register(Sample,{name:'sample',pluralName:'samples',singleViewElementName:'tv-c-single-sample-sub-view',multiViewElementName:'tv-c-multi-sample-sub-view'});return{Sample:Sample};});'use strict';tv.exportTo('tv.c.trace_model',function(){function StackFrame(parentFrame,id,category,title,colorId){if(id===undefined)
+this.memoryDumps[i].addBoundsToRange(this.bounds);},sortMemoryDumps:function(){this.memoryDumps.sort(function(x,y){return x.start-y.start;});tr.model.ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(this.memoryDumps);}};return{Process:Process};});'use strict';tr.exportTo('tr.model',function(){function Sample(cpu,thread,title,start,leafStackFrame,opt_weight,opt_args){tr.model.TimedEvent.call(this,start);this.title=title;this.cpu=cpu;this.thread=thread;this.leafStackFrame=leafStackFrame;this.weight=opt_weight;this.args=opt_args||{};}
+Sample.prototype={__proto__:tr.model.TimedEvent.prototype,get colorId(){return this.leafStackFrame.colorId;},get stackTrace(){return this.leafStackFrame.stackTrace;},getUserFriendlyStackTrace:function(){return this.leafStackFrame.getUserFriendlyStackTrace();},get userFriendlyName(){return'Sample '+' at '+
+tr.b.units.tsString(this.start);}};tr.model.EventRegistry.register(Sample,{name:'sample',pluralName:'samples',singleViewElementName:'tr-c-a-single-sample-sub-view',multiViewElementName:'tr-c-a-multi-sample-sub-view'});return{Sample:Sample};});'use strict';tr.exportTo('tr.model',function(){function StackFrame(parentFrame,id,category,title,colorId){if(id===undefined)
 throw new Error('id must be given');this.parentFrame_=parentFrame;this.id=id;this.category=category||'';this.title=title;this.colorId=colorId;this.children=[];if(this.parentFrame_)
 this.parentFrame_.addChild(this);}
 StackFrame.prototype={get parentFrame(){return this.parentFrame_;},set parentFrame(parentFrame){if(this.parentFrame_)
@@ -2411,19 +2438,23 @@
 this.parentFrame_.addChild(this);},addChild:function(child){this.children.push(child);},removeChild:function(child){var i=this.children.indexOf(child.id);if(i==-1)
 throw new Error('omg');this.children.splice(i,1);},removeAllChildren:function(){for(var i=0;i<this.children.length;i++)
 this.children[i].parentFrame_=undefined;this.children.splice(0,this.children.length);},get stackTrace(){var stack=[];var cur=this;while(cur){stack.push(cur);cur=cur.parentFrame;}
-stack.reverse();return stack;},getUserFriendlyStackTrace:function(){return this.stackTrace.map(function(x){return x.category+': '+x.title;});}};return{StackFrame:StackFrame};});'use strict';tv.exportTo('tv.c.trace_model',function(){var InstantEventType={GLOBAL:1,PROCESS:2};function InstantEvent(category,title,colorId,start,args){tv.c.trace_model.TimedEvent.call(this);this.category=category||'';this.title=title;this.colorId=colorId;this.start=start;this.args=args;this.type=undefined;};InstantEvent.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype};function GlobalInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.GLOBAL;};GlobalInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Global instant event '+this.title+' @ '+
+stack.reverse();return stack;},getUserFriendlyStackTrace:function(){return this.stackTrace.map(function(x){return x.category+': '+x.title;});}};return{StackFrame:StackFrame};});'use strict';tr.exportTo('tr.model',function(){var InstantEventType={GLOBAL:1,PROCESS:2};function InstantEvent(category,title,colorId,start,args){tr.model.TimedEvent.call(this);this.category=category||'';this.title=title;this.colorId=colorId;this.start=start;this.args=args;this.type=undefined;};InstantEvent.prototype={__proto__:tr.model.TimedEvent.prototype};function GlobalInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.GLOBAL;};GlobalInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Global instant event '+this.title+' @ '+
 this.tsString(start);}};function ProcessInstantEvent(category,title,colorId,start,args){InstantEvent.apply(this,arguments);this.type=InstantEventType.PROCESS;};ProcessInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Process-level instant event '+this.title+' @ '+
-this.tsString(start);}};tv.c.trace_model.EventRegistry.register(InstantEvent,{name:'instantEvent',pluralName:'instantEvents',singleViewElementName:'tv-c-single-instant-event-sub-view',multiViewElementName:'tv-c-multi-instant-event-sub-view'});return{GlobalInstantEvent:GlobalInstantEvent,ProcessInstantEvent:ProcessInstantEvent,InstantEventType:InstantEventType,InstantEvent:InstantEvent};});'use strict';tv.exportTo('tv.c.trace_model',function(){function FlowEvent(category,id,title,colorId,start,args,opt_duration){tv.c.trace_model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.start=start;this.args=args;this.id=id;this.startSlice=undefined;this.endSlice=undefined;if(opt_duration!==undefined)
+this.tsString(start);}};tr.model.EventRegistry.register(InstantEvent,{name:'instantEvent',pluralName:'instantEvents',singleViewElementName:'tr-c-a-single-instant-event-sub-view',multiViewElementName:'tr-c-a-multi-instant-event-sub-view'});return{GlobalInstantEvent:GlobalInstantEvent,ProcessInstantEvent:ProcessInstantEvent,InstantEventType:InstantEventType,InstantEvent:InstantEvent};});'use strict';tr.exportTo('tr.model',function(){function FlowEvent(category,id,title,colorId,start,args,opt_duration){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.start=start;this.args=args;this.id=id;this.startSlice=undefined;this.endSlice=undefined;if(opt_duration!==undefined)
 this.duration=opt_duration;}
-FlowEvent.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype,get userFriendlyName(){return'Flow event named '+this.title+' at '+
-tv.c.analysis.tsString(this.timestamp);}};tv.c.trace_model.EventRegistry.register(FlowEvent,{name:'flowEvent',pluralName:'flowEvents',singleViewElementName:'tv-c-single-flow-event-sub-view',multiViewElementName:'tv-c-multi-flow-event-sub-view'});return{FlowEvent:FlowEvent};});'use strict';tv.exportTo('tv.c.trace_model',function(){function GlobalMemoryDump(model,start){tv.c.trace_model.ContainerMemoryDump.call(this,start);this.model=model;this.processMemoryDumps={};}
-GlobalMemoryDump.prototype={__proto__:tv.c.trace_model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Global memory dump '+' at '+
-tv.c.analysis.tsString(this.start);}};tv.c.trace_model.EventRegistry.register(GlobalMemoryDump,{name:'globalMemoryDump',pluralName:'globalMemoryDumps',singleViewElementName:'tv-c-single-global-memory-dump-sub-view',multiViewElementName:'tv-c-multi-global-memory-dump-sub-view'});return{GlobalMemoryDump:GlobalMemoryDump};});'use strict';tv.exportTo('tv.c.trace_model',function(){function EventInfo(title,description,docLinks){this.title=title;this.description=description;this.docLinks=docLinks;this.colorId=tv.b.ui.getColorIdForGeneralPurposeString(title);}
-return{EventInfo:EventInfo};});'use strict';tv.exportTo('tv.c.trace_model',function(){function Alert(info,start,opt_associatedEvents,opt_args){tv.c.trace_model.TimedEvent.call(this,start);this.info=info;this.args=opt_args||{};this.associatedEvents=opt_associatedEvents||[];this.associatedEvents.forEach(function(event){event.associatedAlerts.push(this);},this);}
-Alert.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype,get title(){return this.info.title;},get colorId(){return this.info.colorId;},get userFriendlyName(){return'Alert '+this.title+' at '+
-tv.c.analysis.tsString(this.start);}};tv.c.trace_model.EventRegistry.register(Alert,{name:'alert',pluralName:'alerts',singleViewElementName:'tv-c-a-alert-sub-view',multiViewElementName:'tv-c-a-alert-sub-view'});return{Alert:Alert};});'use strict';tv.exportTo('tv.c.trace_model',function(){function InteractionRecord(title,colorId,start,duration){tv.c.trace_model.TimedEvent.call(this,start);this.title=title;this.colorId=colorId;this.duration=duration;this.args={};this.associatedEvents=[];}
-InteractionRecord.prototype={__proto__:tv.c.trace_model.TimedEvent.prototype,get subSlices(){return[];},get userFriendlyName(){return this.title+' interaction at '+
-tv.c.analysis.tsString(this.start);}};tv.c.trace_model.EventRegistry.register(InteractionRecord,{name:'interaction',pluralName:'interactions',singleViewElementName:'tv-c-single-interaction-record-sub-view',multiViewElementName:'tv-c-multi-interaction-record-sub-view'});return{InteractionRecord:InteractionRecord};});'use strict';tv.exportTo('tv.c',function(){var Importer=tv.c.importer.Importer;var Process=tv.c.trace_model.Process;var Kernel=tv.c.trace_model.Kernel;var GlobalMemoryDump=tv.c.trace_model.GlobalMemoryDump;var GlobalInstantEvent=tv.c.trace_model.GlobalInstantEvent;var FlowEvent=tv.c.trace_model.FlowEvent;var Alert=tv.c.trace_model.Alert;var InteractionRecord=tv.c.trace_model.InteractionRecord;var Sample=tv.c.trace_model.Sample;function ImportOptions(){this.shiftWorldToZero=true;this.pruneEmptyContainers=true;this.customizeModelCallback=undefined;var auditorTypes=tv.c.Auditor.getAllRegisteredTypeInfos();this.auditorConstructors=auditorTypes.map(function(typeInfo){return typeInfo.constructor;});}
+FlowEvent.prototype={__proto__:tr.model.TimedEvent.prototype,get userFriendlyName(){return'Flow event named '+this.title+' at '+
+tr.b.units.tsString(this.timestamp);}};tr.model.EventRegistry.register(FlowEvent,{name:'flowEvent',pluralName:'flowEvents',singleViewElementName:'tr-c-a-single-flow-event-sub-view',multiViewElementName:'tr-c-a-multi-flow-event-sub-view'});return{FlowEvent:FlowEvent};});'use strict';tr.exportTo('tr.model',function(){function GlobalMemoryDump(model,start){tr.model.ContainerMemoryDump.call(this,start);this.model=model;this.processMemoryDumps={};}
+GlobalMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get userFriendlyName(){return'Global memory dump '+' at '+
+tr.b.units.tsString(this.start);},calculateGraphAttributes:function(){this.aggregateMemoryAllocatorDumpAttributes(this.model);tr.b.iterItems(this.processMemoryDumps,function(pid,dump){dump.aggregateMemoryAllocatorDumpAttributes(this.model);},this);tr.b.iterItems(this.processMemoryDumps,function(pid,dump){dump.discountTracingOverhead(this.model);},this);}};tr.model.EventRegistry.register(GlobalMemoryDump,{name:'globalMemoryDump',pluralName:'globalMemoryDumps',singleViewElementName:'tr-c-a-single-global-memory-dump-sub-view',multiViewElementName:'tr-c-a-multi-global-memory-dump-sub-view'});return{GlobalMemoryDump:GlobalMemoryDump};});'use strict';tr.exportTo('tr.model',function(){function EventInfo(title,description,docLinks){this.title=title;this.description=description;this.docLinks=docLinks;this.colorId=tr.b.ui.getColorIdForGeneralPurposeString(title);}
+return{EventInfo:EventInfo};});'use strict';tr.exportTo('tr.model',function(){function Alert(info,start,opt_associatedEvents,opt_args){tr.model.TimedEvent.call(this,start);this.info=info;this.args=opt_args||{};this.associatedEvents=opt_associatedEvents||[];this.associatedEvents.forEach(function(event){event.associatedAlerts.push(this);},this);}
+Alert.prototype={__proto__:tr.model.TimedEvent.prototype,get title(){return this.info.title;},get colorId(){return this.info.colorId;},get userFriendlyName(){return'Alert '+this.title+' at '+
+tr.b.units.tsString(this.start);}};tr.model.EventRegistry.register(Alert,{name:'alert',pluralName:'alerts',singleViewElementName:'tr-c-a-alert-sub-view',multiViewElementName:'tr-c-a-alert-sub-view'});return{Alert:Alert};});'use strict';tr.exportTo('tr.model',function(){function InteractionRecord(title,colorId,start,duration){tr.model.TimedEvent.call(this,start);this.title=title;this.colorId=colorId;this.duration=duration;this.args={};this.associatedEvents=[];}
+InteractionRecord.prototype={__proto__:tr.model.TimedEvent.prototype,get subSlices(){return[];},get userFriendlyName(){return this.title+' interaction at '+
+tr.b.units.tsString(this.start);}};tr.model.EventRegistry.register(InteractionRecord,{name:'interaction',pluralName:'interactions',singleViewElementName:'tr-c-a-single-interaction-record-sub-view',multiViewElementName:'tr-c-a-multi-interaction-record-sub-view'});return{InteractionRecord:InteractionRecord};});'use strict';tr.exportTo('tr.model',function(){function ModelIndices(model){this.flowEventsById_={};model.flowEvents.forEach(function(fe){if(fe.id!==undefined){if(!this.flowEventsById_.hasOwnProperty(fe.id)){this.flowEventsById_[fe.id]=new Array();}
+this.flowEventsById_[fe.id].push(fe);}},this);}
+ModelIndices.prototype={addEventWithId:function(id,event){if(!this.flowEventsById_.hasOwnProperty(id)){this.flowEventsById_[id]=new Array();}
+this.flowEventsById_[id].push(event);},getFlowEventsWithId:function(id){if(!this.flowEventsById_.hasOwnProperty(id))
+return[];return this.flowEventsById_[id];}};return{ModelIndices:ModelIndices};});'use strict';tr.exportTo('tr',function(){var Importer=tr.importer.Importer;var Process=tr.model.Process;var Device=tr.model.Device;var Kernel=tr.model.Kernel;var GlobalMemoryDump=tr.model.GlobalMemoryDump;var GlobalInstantEvent=tr.model.GlobalInstantEvent;var FlowEvent=tr.model.FlowEvent;var Alert=tr.model.Alert;var InteractionRecord=tr.model.InteractionRecord;var Sample=tr.model.Sample;function ImportOptions(){this.shiftWorldToZero=true;this.pruneEmptyContainers=true;this.customizeModelCallback=undefined;var auditorTypes=tr.c.Auditor.getAllRegisteredTypeInfos();this.auditorConstructors=auditorTypes.map(function(typeInfo){return typeInfo.constructor;});}
 ImportOptions.fromArguments=function(args,argsStartIndex){var arg0=args[argsStartIndex+0];if(typeof arg0==='object'){if(!(arg0 instanceof ImportOptions))
 throw new Error('Unexpected');return arg0;}
 var options=new ImportOptions();if(args[argsStartIndex]!==undefined)
@@ -2431,35 +2462,35 @@
 options.pruneEmptyContainers=args[argsStartIndex+1];if(args[argsStartIndex+2])
 options.customizeModelCallback=args[argsStartIndex+2];return options;}
 function ClockSyncRecord(name,ts,args){this.name=name;this.ts=ts;this.args=args;}
-function TraceModel(opt_eventData,opt_options){tv.c.trace_model.EventContainer.call(this);tv.b.EventTarget.decorate(this);this.faviconHue='blue';this.kernel=new Kernel(this);this.processes={};this.metadata=[];this.categories=[];this.bounds=new tv.b.Range();this.instantEvents=[];this.flowEvents=[];this.clockSyncRecords=[];this.stackFrames={};this.samples=[];this.alerts=[];this.interaction_records=[];this.flowIntervalTree=new tv.b.IntervalTree(function(f){return f.start;},function(f){return f.end;});this.globalMemoryDumps=[];this.annotationsByGuid_={};this.importWarnings_=[];this.reportedImportWarnings_={};var options=ImportOptions.fromArguments(arguments,1);if(opt_eventData)
+function Model(opt_eventData,opt_options){tr.model.EventContainer.call(this);tr.b.EventTarget.decorate(this);this.faviconHue='blue';this.device=new Device(this);this.kernel=new Kernel(this);this.processes={};this.metadata=[];this.categories=[];this.bounds=new tr.b.Range();this.instantEvents=[];this.flowEvents=[];this.clockSyncRecords=[];this.stackFrames={};this.samples=[];this.alerts=[];this.interaction_records=[];this.flowIntervalTree=new tr.b.IntervalTree(function(f){return f.start;},function(f){return f.end;});this.globalMemoryDumps=[];this.annotationsByGuid_={};this.importWarnings_=[];this.reportedImportWarnings_={};this.modelIndices=undefined;var options=ImportOptions.fromArguments(arguments,1);if(opt_eventData)
 this.importTraces([opt_eventData],options);}
-TraceModel.prototype={__proto__:tv.c.trace_model.EventContainer.prototype,iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,GlobalMemoryDump))
+Model.prototype={__proto__:tr.model.EventContainer.prototype,iterateAllEventsInThisContainer:function(eventTypePredicate,callback,opt_this){if(eventTypePredicate.call(opt_this,GlobalMemoryDump))
 this.globalMemoryDumps.forEach(callback,opt_this);if(eventTypePredicate.call(opt_this,GlobalInstantEvent))
 this.instantEvents.forEach(callback,opt_this);if(eventTypePredicate.call(opt_this,FlowEvent))
 this.flowEvents.forEach(callback,opt_this);if(eventTypePredicate.call(opt_this,Alert))
 this.alerts.forEach(callback,opt_this);if(eventTypePredicate.call(opt_this,InteractionRecord))
 this.interaction_records.forEach(callback,opt_this);if(eventTypePredicate.call(opt_this,Sample))
-this.samples.forEach(callback,opt_this);},iterateAllChildEventContainers:function(callback,opt_this){callback.call(opt_this,this.kernel);for(var pid in this.processes)
+this.samples.forEach(callback,opt_this);},iterateAllChildEventContainers:function(callback,opt_this){callback.call(opt_this,this.device);callback.call(opt_this,this.kernel);for(var pid in this.processes)
 callback.call(opt_this,this.processes[pid]);},iterateAllPersistableObjects:function(callback){this.kernel.iterateAllPersistableObjects(callback);for(var pid in this.processes)
 this.processes[pid].iterateAllPersistableObjects(callback);},updateBounds:function(){this.bounds.reset();var bounds=this.bounds;this.iterateAllChildEventContainers(function(ec){ec.updateBounds();bounds.addRange(ec.bounds);});this.iterateAllEventsInThisContainer(function(eventConstructor){return true;},function(event){event.addBoundsToRange(bounds);});},shiftWorldToZero:function(){var shiftAmount=-this.bounds.min;this.iterateAllChildEventContainers(function(ec){ec.shiftTimestampsForward(shiftAmount);});this.iterateAllEventsInThisContainer(function(eventConstructor){return true;},function(event){event.start+=shiftAmount;});this.updateBounds();},get numProcesses(){var n=0;for(var p in this.processes)
 n++;return n;},getProcess:function(pid){return this.processes[pid];},getOrCreateProcess:function(pid){if(!this.processes[pid])
 this.processes[pid]=new Process(this,pid);return this.processes[pid];},pushInstantEvent:function(instantEvent){this.instantEvents.push(instantEvent);},addStackFrame:function(stackFrame){if(this.stackFrames[stackFrame.id])
-throw new Error('Stack frame already exists');this.stackFrames[stackFrame.id]=stackFrame;return stackFrame;},addInteractionRecord:function(ir1){this.interaction_records.push(ir1);},getClockSyncRecordsNamed:function(name){return this.clockSyncRecords.filter(function(x){return x.name===name;});},updateCategories_:function(){var categoriesDict={};this.kernel.addCategoriesToDict(categoriesDict);for(var pid in this.processes)
+throw new Error('Stack frame already exists');this.stackFrames[stackFrame.id]=stackFrame;return stackFrame;},addInteractionRecord:function(ir1){this.interaction_records.push(ir1);},getClockSyncRecordsNamed:function(name){return this.clockSyncRecords.filter(function(x){return x.name===name;});},updateCategories_:function(){var categoriesDict={};this.device.addCategoriesToDict(categoriesDict);this.kernel.addCategoriesToDict(categoriesDict);for(var pid in this.processes)
 this.processes[pid].addCategoriesToDict(categoriesDict);this.categories=[];for(var category in categoriesDict)
 if(category!='')
 this.categories.push(category);},getAllThreads:function(){var threads=[];for(var tid in this.kernel.threads){threads.push(process.threads[tid]);}
 for(var pid in this.processes){var process=this.processes[pid];for(var tid in process.threads){threads.push(process.threads[tid]);}}
 return threads;},getAllProcesses:function(){var processes=[];for(var pid in this.processes)
-processes.push(this.processes[pid]);return processes;},getAllCounters:function(){var counters=[];counters.push.apply(counters,tv.b.dictionaryValues(this.kernel.counters));for(var pid in this.processes){var process=this.processes[pid];for(var tid in process.counters){counters.push(process.counters[tid]);}}
+processes.push(this.processes[pid]);return processes;},getAllCounters:function(){var counters=[];counters.push.apply(counters,tr.b.dictionaryValues(this.device.counters));counters.push.apply(counters,tr.b.dictionaryValues(this.kernel.counters));for(var pid in this.processes){var process=this.processes[pid];for(var tid in process.counters){counters.push(process.counters[tid]);}}
 return counters;},getAnnotationByGUID:function(guid){return this.annotationsByGuid_[guid];},addAnnotation:function(annotation){if(!annotation.guid)
-throw new Error('Annotation with undefined guid given');this.annotationsByGuid_[annotation.guid]=annotation;tv.b.dispatchSimpleEvent(this,'annotationChange');},removeAnnotation:function(annotation){this.annotationsByGuid_[annotation.guid].onRemove();delete this.annotationsByGuid_[annotation.guid];tv.b.dispatchSimpleEvent(this,'annotationChange');},getAllAnnotations:function(){return tv.b.dictionaryValues(this.annotationsByGuid_);},findAllThreadsNamed:function(name){var namedThreads=[];namedThreads.push.apply(namedThreads,this.kernel.findAllThreadsNamed(name));for(var pid in this.processes){namedThreads.push.apply(namedThreads,this.processes[pid].findAllThreadsNamed(name));}
-return namedThreads;},createImporter_:function(eventData){var importerConstructor=tv.c.importer.Importer.findImporterFor(eventData);if(!importerConstructor)
-throw new Error('Could not find an importer for the provided eventData.');var importer=new importerConstructor(this,eventData);return importer;},importTraces:function(traces,opt_options){var progressMeter={update:function(msg){}};var options=ImportOptions.fromArguments(arguments,1);var task=this.createImportTracesTask(progressMeter,traces,options);tv.b.Task.RunSynchronously(task);},importTracesWithProgressDialog:function(traces,opt_options){var options=ImportOptions.fromArguments(arguments,1);var overlay=tv.b.ui.Overlay();overlay.title='Importing...';overlay.userCanClose=false;overlay.msgEl=document.createElement('div');overlay.appendChild(overlay.msgEl);overlay.msgEl.style.margin='20px';overlay.update=function(msg){this.msgEl.textContent=msg;}
-overlay.visible=true;var task=this.createImportTracesTask(overlay,traces,options);var promise=tv.b.Task.RunWhenIdle(task);promise.then(function(){overlay.visible=false;},function(err){overlay.visible=false;});return promise;},hasEventDataDecoder_:function(importers){if(importers.length===0)
+throw new Error('Annotation with undefined guid given');this.annotationsByGuid_[annotation.guid]=annotation;tr.b.dispatchSimpleEvent(this,'annotationChange');},removeAnnotation:function(annotation){this.annotationsByGuid_[annotation.guid].onRemove();delete this.annotationsByGuid_[annotation.guid];tr.b.dispatchSimpleEvent(this,'annotationChange');},getAllAnnotations:function(){return tr.b.dictionaryValues(this.annotationsByGuid_);},findAllThreadsNamed:function(name){var namedThreads=[];namedThreads.push.apply(namedThreads,this.kernel.findAllThreadsNamed(name));for(var pid in this.processes){namedThreads.push.apply(namedThreads,this.processes[pid].findAllThreadsNamed(name));}
+return namedThreads;},createImporter_:function(eventData){var importerConstructor=tr.importer.Importer.findImporterFor(eventData);if(!importerConstructor)
+throw new Error('Could not find an importer for the provided eventData.');var importer=new importerConstructor(this,eventData);return importer;},importTraces:function(traces,opt_options){var progressMeter={update:function(msg){}};var options=ImportOptions.fromArguments(arguments,1);var task=this.createImportTracesTask(progressMeter,traces,options);tr.b.Task.RunSynchronously(task);},importTracesWithProgressDialog:function(traces,opt_options){var options=ImportOptions.fromArguments(arguments,1);var overlay=tr.b.ui.Overlay();overlay.title='Importing...';overlay.userCanClose=false;overlay.msgEl=document.createElement('div');overlay.appendChild(overlay.msgEl);overlay.msgEl.style.margin='20px';overlay.update=function(msg){this.msgEl.textContent=msg;}
+overlay.visible=true;var task=this.createImportTracesTask(overlay,traces,options);var promise=tr.b.Task.RunWhenIdle(task);promise.then(function(){overlay.visible=false;},function(err){overlay.visible=false;});return promise;},hasEventDataDecoder_:function(importers){if(importers.length===0)
 return false;for(var i=0;i<importers.length;++i){if(!importers[i].isTraceDataContainer())
 return true;}
 return false;},createImportTracesTask:function(progressMeter,traces,opt_options){var options=ImportOptions.fromArguments(arguments,2);if(this.importing_)
-throw new Error('Already importing.');this.importing_=true;var importTask=new tv.b.Task(function(){progressMeter.update('I will now import your traces for you...');},this);var lastTask=importTask;var importers=[];lastTask=lastTask.after(function(){traces=traces.slice(0);progressMeter.update('Creating importers...');for(var i=0;i<traces.length;++i)
+throw new Error('Already importing.');this.importing_=true;var importTask=new tr.b.Task(function(){progressMeter.update('I will now import your traces for you...');},this);var lastTask=importTask;var importers=[];lastTask=lastTask.after(function(){traces=traces.slice(0);progressMeter.update('Creating importers...');for(var i=0;i<traces.length;++i)
 importers.push(this.createImporter_(traces[i]));for(var i=0;i<importers.length;i++){var subtraces=importers[i].extractSubtraces();for(var j=0;j<subtraces.length;j++){try{traces.push(subtraces[j]);importers.push(this.createImporter_(subtraces[j]));}catch(error){console.warn(error.name+': '+error.message);continue;}}}
 if(traces.length&&!this.hasEventDataDecoder_(importers)){throw new Error('Could not find an importer for '+'the provided eventData.');}
 importers.sort(function(x,y){return x.importPriority-y.importPriority;});},this);lastTask=lastTask.after(function(task){importers.forEach(function(importer,index){task.subTask(function(){progressMeter.update('Importing '+(index+1)+' of '+importers.length);importer.importEvents();},this);},this);},this);if(options.customizeModelCallback){lastTask=lastTask.after(function(task){options.customizeModelCallback(this);},this);}
@@ -2472,10 +2503,10 @@
 this.shiftWorldToZero();},this);lastTask=lastTask.after(function(){progressMeter.update('Building flow event map...');for(var i=0;i<this.flowEvents.length;++i){var flowEvent=this.flowEvents[i];this.flowIntervalTree.insert(flowEvent);}
 this.flowIntervalTree.updateHighValues();},this);lastTask=lastTask.after(function(){progressMeter.update('Joining object refs...');for(var i=0;i<importers.length;i++)
 importers[i].joinRefs();},this);lastTask=lastTask.after(function(){progressMeter.update('Cleaning up undeleted objects...');for(var pid in this.processes)
-this.processes[pid].autoDeleteObjects(this.bounds.max);},this);lastTask=lastTask.after(function(){progressMeter.update('Finalizing memory dumps...');this.globalMemoryDumps.sort(function(x,y){return x.start-y.start;});for(var pid in this.processes)
-this.processes[pid].finalizeMemoryDumps();},this);lastTask=lastTask.after(function(){progressMeter.update('Initializing objects (step 2/2)...');for(var pid in this.processes)
-this.processes[pid].initializeObjects();},this);lastTask=lastTask.after(function(){progressMeter.update('Running auditors...');auditors.forEach(function(auditor){auditor.runAudit();});this.interaction_records.sort(function(x,y){return x.start-y.start;});this.alerts.sort(function(x,y){return x.start-y.start;});this.updateBounds();},this);lastTask.after(function(){this.importing_=false;},this);return importTask;},importWarning:function(data){this.importWarnings_.push(data);if(this.reportedImportWarnings_[data.type]===true)
-return;console.warn(data.message);this.reportedImportWarnings_[data.type]=true;},get hasImportWarnings(){return(this.importWarnings_.length>0);},get importWarnings(){return this.importWarnings_;}};return{ImportOptions:ImportOptions,ClockSyncRecord:ClockSyncRecord,TraceModel:TraceModel};});'use strict';tv.exportTo('tv.c',function(){var EventRegistry=tv.c.trace_model.EventRegistry;var RequestSelectionChangeEvent=tv.b.Event.bind(undefined,'requestSelectionChange',true,false);function Selection(opt_events){this.sunburst_zoom_level=undefined;this.bounds_dirty_=true;this.bounds_=new tv.b.Range();this.length_=0;this.guid_=tv.b.GUID.allocate();this.pushed_guids_={};if(opt_events){if(opt_events instanceof Array){for(var i=0;i<opt_events.length;i++)
+this.processes[pid].autoDeleteObjects(this.bounds.max);},this);lastTask=lastTask.after(function(){progressMeter.update('Sorting memory dumps...');this.globalMemoryDumps.sort(function(x,y){return x.start-y.start;});for(var pid in this.processes)
+this.processes[pid].sortMemoryDumps();},this);lastTask=lastTask.after(function(){progressMeter.update('Calculating memory dump graph attributes...');this.globalMemoryDumps.forEach(function(dump){dump.calculateGraphAttributes();});},this);lastTask=lastTask.after(function(){progressMeter.update('Initializing objects (step 2/2)...');for(var pid in this.processes)
+this.processes[pid].initializeObjects();},this);lastTask=lastTask.after(function(){progressMeter.update('Building flow event indices...');this.modelIndices=new tr.model.ModelIndices(this);},this);lastTask=lastTask.after(function(){progressMeter.update('Running auditors...');auditors.forEach(function(auditor){auditor.runAudit();});this.interaction_records.sort(function(x,y){return x.start-y.start;});this.alerts.sort(function(x,y){return x.start-y.start;});this.updateBounds();},this);lastTask.after(function(){this.importing_=false;},this);return importTask;},importWarning:function(data){this.importWarnings_.push(data);if(this.reportedImportWarnings_[data.type]===true)
+return;console.warn(data.message);this.reportedImportWarnings_[data.type]=true;},get hasImportWarnings(){return(this.importWarnings_.length>0);},get importWarnings(){return this.importWarnings_;}};return{ImportOptions:ImportOptions,ClockSyncRecord:ClockSyncRecord,Model:Model};});'use strict';tr.exportTo('tr.c',function(){var EventRegistry=tr.model.EventRegistry;var RequestSelectionChangeEvent=tr.b.Event.bind(undefined,'requestSelectionChange',true,false);function Selection(opt_events){this.sunburst_zoom_level=undefined;this.bounds_dirty_=true;this.bounds_=new tr.b.Range();this.length_=0;this.guid_=tr.b.GUID.allocate();this.pushed_guids_={};if(opt_events){if(opt_events instanceof Array){for(var i=0;i<opt_events.length;i++)
 this.push(opt_events[i]);}else{this.push(opt_events);}}}
 Selection.prototype={__proto__:Object.prototype,get bounds(){if(this.bounds_dirty_){this.bounds_.reset();for(var i=0;i<this.length_;i++)
 this[i].addBoundsToRange(this.bounds_);this.bounds_dirty_=false;}
@@ -2491,7 +2522,7 @@
 return false;}
 return true;},getEventsOrganizedByBaseType:function(opt_pruneEmpty){var events={};var allTypeInfos=EventRegistry.getAllRegisteredTypeInfos();allTypeInfos.forEach(function(eventTypeInfo){events[eventTypeInfo.metadata.name]=new Selection();if(this.sunburst_zoom_level!==undefined)
 events[eventTypeInfo.metadata.name].sunburst_zoom_level=this.sunburst_zoom_level;},this);this.forEach(function(event,i){var maxEventIndex=-1;var maxEventTypeInfo=undefined;allTypeInfos.forEach(function(eventTypeInfo,eventIndex){if(!(event instanceof eventTypeInfo.constructor))
-return;if(eventIndex>maxEventIndex){maxEventIndex=eventIndex;maxEventTypeInfo=eventTypeInfo;}});if(maxEventIndex==-1){console.log(event);throw new Error('Unrecgonized event type');}
+return;if(eventIndex>maxEventIndex){maxEventIndex=eventIndex;maxEventTypeInfo=eventTypeInfo;}});if(maxEventIndex==-1){console.log(event);throw new Error('Unrecognized event type');}
 events[maxEventTypeInfo.metadata.name].push(event);});if(opt_pruneEmpty){var prunedEvents={};for(var eventType in events){if(events[eventType].length>0)
 prunedEvents[eventType]=events[eventType];}
 return prunedEvents;}else{return events;}},getEventsOrganizedByTitle:function(){var eventsByTitle={};for(var i=0;i<this.length;i++){var event=this[i];if(event.title===undefined)
@@ -2500,9 +2531,9 @@
 return eventsByTitle;},enumEventsOfType:function(type,func){for(var i=0;i<this.length_;i++)
 if(this[i]instanceof type)
 func(this[i]);},get userFriendlyName(){if(this.length===0){throw new Error('Empty selection');}
-var eventsByBaseType=this.getEventsOrganizedByBaseType(true);var eventTypeName=tv.b.dictionaryKeys(eventsByBaseType)[0];if(this.length===1){var tmp=EventRegistry.getUserFriendlySingularName(eventTypeName);return this[0].userFriendlyName;}
-var numEventTypes=tv.b.dictionaryLength(eventsByBaseType);if(numEventTypes!==1){return this.length+' events of various types';}
-var tmp=EventRegistry.getUserFriendlyPluralName(eventTypeName);return this.length+' '+tmp;},getShiftedSelection:function(viewport,offset){var newSelection=new Selection();for(var i=0;i<this.length_;i++){var event=this[i];if(event instanceof tv.c.trace_model.FlowEvent){if(offset>0){newSelection.push(event.endSlice);}else if(offset<0){newSelection.push(event.startSlice);}else{}
+var eventsByBaseType=this.getEventsOrganizedByBaseType(true);var eventTypeName=tr.b.dictionaryKeys(eventsByBaseType)[0];if(this.length===1){var tmp=EventRegistry.getUserFriendlySingularName(eventTypeName);return this[0].userFriendlyName;}
+var numEventTypes=tr.b.dictionaryLength(eventsByBaseType);if(numEventTypes!==1){return this.length+' events of various types';}
+var tmp=EventRegistry.getUserFriendlyPluralName(eventTypeName);return this.length+' '+tmp;},getShiftedSelection:function(viewport,offset){var newSelection=new Selection();for(var i=0;i<this.length_;i++){var event=this[i];if(event instanceof tr.model.FlowEvent){if(offset>0){newSelection.push(event.endSlice);}else if(offset<0){newSelection.push(event.startSlice);}else{}
 continue;}
 var track=viewport.trackForEvent(event);track.addEventNearToProvidedEventToSelection(event,offset,newSelection);}
 if(newSelection.length==0)
@@ -2512,38 +2543,40 @@
 if(!fn.call(opt_this,this[i],i))
 return false;return true;},some:function(fn,opt_this){for(var i=0;i<this.length;i++)
 if(fn.call(opt_this,this[i],i))
-return true;return false;}};return{Selection:Selection,RequestSelectionChangeEvent:RequestSelectionChangeEvent};});'use strict';Polymer('tracing-analysis-sub-view',{set tabLabel(label){return this.setAttribute('tab-label',label);},get tabLabel(){return this.getAttribute('tab-label');},get requiresTallView(){return false;},get relatedEventsToHighlight(){return undefined;},set selection(selection){throw new Error('Not implemented!');},get selection(){throw new Error('Not implemented!');}});'use strict';tv.exportTo('tv.c.analysis',function(){function createTimeSpan(duration){if(duration===undefined)
-return'';var span=document.createElement('tv-c-a-time-span');span.duration=duration;return span;}
-return{createTimeSpan:createTimeSpan};});'use strict';Polymer('tv-c-a-time-span',{ready:function(){this.warning_=undefined;this.duration_=undefined;},get duration(){return this.duration_;},set duration(duration){this.duration_=duration;this.$.content.textContent=tv.c.analysis.tsString(duration);},get warning(){return this.warning_;},set warning(warning){this.warning_=warning;var warningEl=this.$.warning;if(this.warning_){warningEl.title=warning;warningEl.style.display='';}else{warningEl.title='';warningEl.style.display='none';}}});'use strict';tv.exportTo('tv.c.analysis',function(){function createTimeStamp(timestamp){if(timestamp===undefined)
-return'';var span=document.createElement('tv-c-a-time-stamp');span.timestamp=timestamp;return span;}
-return{createTimeStamp:createTimeStamp};});'use strict';Polymer('tv-c-a-time-stamp',{ready:function(){this.timestamp_=undefined;},get timestamp(){return this.timestamp_;},set timestamp(timestamp){this.timestamp_=timestamp;this.shadowRoot.textContent=tv.c.analysis.tsString(timestamp);}});'use strict';Polymer('tv-c-analysis-link',{ready:function(){this.addEventListener('click',this.onClicked_.bind(this));this.selection_=undefined;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.textContent=selection.userFriendlyName;},setSelectionAndContent:function(selection,opt_textContent){this.selection_=selection;if(opt_textContent)
-this.textContent=opt_textContent;},onClicked_:function(){if(!this.selection_)
-return;var event=new tv.c.RequestSelectionChangeEvent();if(typeof this.selection_==='function')
-event.selection=this.selection_();else
-event.selection=this.selection_;this.dispatchEvent(event);}});'use strict';tv.exportTo('tv.b',function(){function TimeDuration(duration){this.duration=duration;};TimeDuration.prototype={toString:function(){return this.duration.toFixed(3)+' ms';}};function TimeStamp(timestamp){this.timestamp=timestamp;};TimeStamp.prototype={toString:function(){return this.timestamp.toFixed(4)+' ms';}};return{TimeStamp:TimeStamp,TimeDuration:TimeDuration};});'use strict';function isTable(object){if(!(object instanceof Array)||(object.length<2))return false;for(var colName in object[0]){if(typeof colName!=='string')return false;}
-for(var i=0;i<object.length;++i){if(!(object[i]instanceof Object))return false;for(var colName in object[i]){if(i&&(object[0][colName]===undefined))return false;var cellType=typeof object[i][colName];if(cellType!=='string'&&cellType!='number')return false;}
-if(i){for(var colName in object[0]){if(object[i][colName]===undefined)return false;}}}
+return true;return false;}};return{Selection:Selection,RequestSelectionChangeEvent:RequestSelectionChangeEvent};});'use strict';Polymer('tr-c-a-sub-view',{set tabLabel(label){return this.setAttribute('tab-label',label);},get tabLabel(){return this.getAttribute('tab-label');},get requiresTallView(){return false;},get relatedEventsToHighlight(){return undefined;},set selection(selection){throw new Error('Not implemented!');},get selection(){throw new Error('Not implemented!');}});'use strict';tr.exportTo('tr.b',function(){function _iterateElementDeeplyImpl(element,cb,thisArg,includeElement){if(includeElement){if(cb.call(thisArg,element))
 return true;}
-Polymer('tv-c-analysis-generic-object-view',{ready:function(){this.object_=undefined;},get object(){return this.object_;},set object(object){this.object_=object;this.updateContents_();},updateContents_:function(){this.$.content.textContent='';this.appendElementsForType_('',this.object_,0,0,5,'');},appendElementsForType_:function(label,object,indent,depth,maxDepth,suffix){if(depth>maxDepth){this.appendSimpleText_(label,indent,'<recursion limit reached>',suffix);return;}
-if(object===undefined){this.appendSimpleText_(label,indent,'undefined',suffix);return;}
-if(object===null){this.appendSimpleText_(label,indent,'null',suffix);return;}
-if(!(object instanceof Object)){var type=typeof object;if(type=='string'){var objectReplaced=false;if((object[0]=='{'&&object[object.length-1]=='}')||(object[0]=='['&&object[object.length-1]==']')){try{object=JSON.parse(object);objectReplaced=true;}catch(e){}}
-if(!objectReplaced){if(object.indexOf('\n')!==-1){var lines=object.split('\n');lines.forEach(function(line,i){var text,ioff,ll,ss;if(i==0){text='"'+line;ioff=0;ll=label;ss='';}else if(i<lines.length-1){text=line;ioff=1;ll='';ss='';}else{text=line+'"';ioff=1;ll='';ss=suffix;}
-var el=this.appendSimpleText_(ll,indent+ioff*label.length+ioff,text,ss);el.style.whiteSpace='pre';return el;},this);return;}else{this.appendSimpleText_(label,indent,'"'+object+'"',suffix);return;}}
-else{}}else{return this.appendSimpleText_(label,indent,object,suffix);}}
-if(object instanceof tv.c.trace_model.ObjectSnapshot){var link=document.createElement('tv-c-analysis-link');link.selection=new tv.c.Selection(object);this.appendElementWithLabel_(label,indent,link,suffix);return;}
-if(object instanceof tv.c.trace_model.ObjectInstance){var link=document.createElement('tv-c-analysis-link');link.selection=new tv.c.Selection(object);this.appendElementWithLabel_(label,indent,link,suffix);return;}
-if(object instanceof tv.b.Rect){this.appendSimpleText_(label,indent,object.toString(),suffix);return;}
-if(object instanceof tv.b.TimeDuration){var el=this.ownerDocument.createElement('tv-c-a-time-span');el.duration=object.duration;this.appendElementWithLabel_(label,indent,el,suffix);return;}
-if(object instanceof tv.b.TimeStamp){var el=this.ownerDocument.createElement('tv-c-a-time-stamp');el.timestamp=object.timestamp;this.appendElementWithLabel_(label,indent,el,suffix);return;}
-if(object instanceof Array){this.appendElementsForArray_(label,object,indent,depth,maxDepth,suffix);return;}
-this.appendElementsForObject_(label,object,indent,depth,maxDepth,suffix);},appendElementsForArray_:function(label,object,indent,depth,maxDepth,suffix){if(object.length==0){this.appendSimpleText_(label,indent,'[]',suffix);return;}
-if(isTable(object)){var table=document.createElement('table');var tr=document.createElement('tr');table.appendChild(tr);var columns=[];for(var colName in object[0]){columns.push(colName);var th=document.createElement('th');th.textContent=colName;tr.appendChild(th);}
-object.forEach(function(row){var tr=document.createElement('tr');table.appendChild(tr);columns.forEach(function(colName){var cell=row[colName];var td=document.createElement('td');td.textContent=cell;td.style.textAlign=isNaN(parseFloat(cell))?'left':'right';tr.appendChild(td);});});this.appendElementWithLabel_(label,indent,table,suffix);return;}
-this.appendElementsForType_(label+'[',object[0],indent,depth+1,maxDepth,object.length>1?',':']'+suffix);for(var i=1;i<object.length;i++){this.appendElementsForType_('',object[i],indent+label.length+1,depth+1,maxDepth,i<object.length-1?',':']'+suffix);}
-return;},appendElementsForObject_:function(label,object,indent,depth,maxDepth,suffix){var keys=tv.b.dictionaryKeys(object);if(keys.length==0){this.appendSimpleText_(label,indent,'{}',suffix);return;}
-this.appendElementsForType_(label+'{'+keys[0]+': ',object[keys[0]],indent,depth,maxDepth,keys.length>1?',':'}'+suffix);for(var i=1;i<keys.length;i++){this.appendElementsForType_(keys[i]+': ',object[keys[i]],indent+label.length+1,depth+1,maxDepth,i<keys.length-1?',':'}'+suffix);}},appendElementWithLabel_:function(label,indent,dataElement,suffix){var row=document.createElement('div');var indentSpan=document.createElement('span');indentSpan.style.whiteSpace='pre';for(var i=0;i<indent;i++)
-indentSpan.textContent+=' ';row.appendChild(indentSpan);var labelSpan=document.createElement('span');labelSpan.textContent=label;row.appendChild(labelSpan);row.appendChild(dataElement);var suffixSpan=document.createElement('span');suffixSpan.textContent=suffix;row.appendChild(suffixSpan);row.dataElement=dataElement;this.$.content.appendChild(row);},appendSimpleText_:function(label,indent,text,suffix){var el=this.ownerDocument.createElement('span');el.textContent=text;this.appendElementWithLabel_(label,indent,el,suffix);return el;}});'use strict';Polymer('tv-c-analysis-generic-object-view-with-label',{ready:function(){this.labelEl_=document.createElement('div');this.genericObjectView_=document.createElement('tv-c-analysis-generic-object-view');this.shadowRoot.appendChild(this.labelEl_);this.shadowRoot.appendChild(this.genericObjectView_);},get label(){return this.labelEl_.textContent;},set label(label){this.labelEl_.textContent=label;},get object(){return this.genericObjectView_.object;},set object(object){this.genericObjectView_.object=object;}});'use strict';Polymer('tv-c-a-stack-frame',{ready:function(){this.stackFrame_=undefined;},get stackFrame(){return this.stackFrame_;},set stackFrame(stackFrame){this.stackFrame_=stackFrame;this.$.ov.object=stackFrame.getUserFriendlyStackTrace();}});'use strict';Polymer('tracing-analysis-toggle-container',{publish:{visible:{value:false,reflect:true}},created:function(){this.toggleListeners_=[];},toggleVisible:function(){this.visible=!this.visible;},setToggleListener:function(target,eventType){var listenerFunction=this.toggleVisible.bind(this);target.addEventListener(eventType,listenerFunction,false);this.toggleListeners_.push({target:target,eventType:eventType,listenerFunction:listenerFunction});},clearToggleListener:function(target,eventType){for(var i=0;i<this.toggleListeners_.length;i++){var listener=this.toggleListeners_[i];if(listener.target===target&&listener.eventType===eventType){target.removeEventListener(listener.eventType,listener.listenerFunction,false);this.toggleListeners_.splice(i,1);return;}}}});'use strict';(function(){var RIGHT_ARROW=String.fromCharCode(0x25b6);var UNSORTED_ARROW=String.fromCharCode(0x25BF);var ASCENDING_ARROW=String.fromCharCode(0x25BE);var DESCENDING_ARROW=String.fromCharCode(0x25B4);var BASIC_INDENTATION=8;Polymer('tracing-analysis-nested-table',{created:function(){this.supportsSelection_=false;this.cellSelectionMode_=false;this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;this.tableColumns_=[];this.tableRows_=[];this.tableRowsInfo_=[];this.tableFooterRows_=[];this.sortColumnIndex_=undefined;this.sortDescending_=false;this.columnsWithExpandButtons_=[];this.headerCells_=[];this.showHeader_=true;this.emptyValue_=undefined;},ready:function(){this.$.body.addEventListener('keydown',this.onKeyDown_.bind(this),true);},clear:function(){this.supportsSelection_=false;this.cellSelectionMode_=false;this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;this.textContent='';this.tableColumns_=[];this.tableRows_=[];this.tableRowsInfo_=new WeakMap();this.tableFooterRows_=[];this.tableFooterRowsInfo_=new WeakMap();this.sortColumnIndex_=undefined;this.sortDescending_=false;this.columnsWithExpandButtons_=[];this.headerCells_=[];},get showHeader(){return this.showHeader_;},set showHeader(showHeader){this.showHeader_=showHeader;this.scheduleRebuildHeaders_();},get emptyValue(){return this.emptyValue_;},set emptyValue(emptyValue){var previousEmptyValue=this.emptyValue_;this.emptyValue_=emptyValue;if(this.tableRows_.length===0&&emptyValue!==previousEmptyValue)
+if(element.shadowRoot){if(_iterateElementDeeplyImpl(element.shadowRoot,cb,thisArg,false))
+return true;}
+for(var i=0;i<element.children.length;i++){if(_iterateElementDeeplyImpl(element.children[i],cb,thisArg,true))
+return true;}}
+function iterateElementDeeply(element,cb,thisArg){_iterateElementDeeplyImpl(element,cb,thisArg,false);}
+function findDeepElementMatchingPredicate(element,predicate){var foundElement=undefined;function matches(element){var match=predicate(element);if(!match)
+return false;foundElement=element;return true;}
+iterateElementDeeply(element,matches);return foundElement;}
+function findDeepElementsMatchingPredicate(element,predicate){var foundElements=[];function matches(element){var match=predicate(element);if(match){foundElements.push(element);}
+return false;}
+iterateElementDeeply(element,matches);return foundElements;}
+function findDeepElementMatching(element,selector){return findDeepElementMatchingPredicate(element,function(element){return element.matches(selector);});}
+function findDeepElementsMatching(element,selector){return findDeepElementsMatchingPredicate(element,function(element){return element.matches(selector);});}
+function findDeepElementWithTextContent(element,re){return findDeepElementMatchingPredicate(element,function(element){if(element.children.length!==0)
+return false;return re.test(element.textContent);});}
+return{iterateElementDeeply:iterateElementDeeply,findDeepElementMatching:findDeepElementMatching,findDeepElementsMatching:findDeepElementsMatching,findDeepElementMatchingPredicate:findDeepElementMatchingPredicate,findDeepElementsMatchingPredicate:findDeepElementsMatchingPredicate,findDeepElementWithTextContent:findDeepElementWithTextContent};});'use strict';tr.exportTo('tr.b.units',function(){function TimeDuration(duration){this.duration=duration;};TimeDuration.prototype={toString:function(){return this.duration.toFixed(3)+' ms';}};return{TimeDuration:TimeDuration};});'use strict';tr.exportTo('tr.b.units',function(){function createTimeSpan(duration){if(duration===undefined)
+return'';var span=document.createElement('tr-b-u-time-duration-span');span.duration=duration;return span;}
+tr.b.units.Time.addEventListener('display-unit-changed',function(e){tr.b.findDeepElementsMatching(document.body,'tr-b-u-time-duration-span').forEach(function(el){el.updateContent_();});});return{createTimeSpan:createTimeSpan};});'use strict';Polymer('tr-b-u-time-duration-span',{ready:function(){this.warning_=undefined;this.duration_=undefined;},get duration(){return this.duration_;},set duration(duration){if(duration instanceof tr.b.units.TimeDuration)
+this.duration_=duration.duration;else
+this.duration_=duration;this.updateContent_();},updateContent_:function(){var content=tr.b.units.Time.currentDisplayUnit.format(this.duration_);this.$.content.textContent=content;},get warning(){return this.warning_;},set warning(warning){this.warning_=warning;var warningEl=this.$.warning;if(this.warning_){warningEl.title=warning;warningEl.style.display='';}else{warningEl.title='';warningEl.style.display='none';}}});'use strict';tr.exportTo('tr.b.units',function(){function TimeStamp(timestamp){this.timestamp=timestamp;};TimeStamp.prototype={toString:function(){return this.timestamp.toFixed(4)+' ms';}};return{TimeStamp:TimeStamp};});'use strict';tr.exportTo('tr.b.units',function(){function createTimeStampSpan(timestamp){if(timestamp===undefined)
+return'';var span=document.createElement('tr-b-u-time-stamp-span');span.timestamp=timestamp;return span;}
+tr.b.units.Time.addEventListener('display-unit-changed',function(e){tr.b.findDeepElementsMatching(document.body,'tr-b-u-time-stamp-span').forEach(function(el){el.updateContent_();});});return{createTimeStampSpan:createTimeStampSpan};});'use strict';Polymer('tr-b-u-time-stamp-span',{ready:function(){this.timestamp_=undefined;},get timestamp(){return this.timestamp_;},set timestamp(timestamp){if(timestamp instanceof tr.b.units.TimeStamp)
+this.timestamp_=timestamp.timestamp;else
+this.timestamp_=timestamp;this.updateContent_();},updateContent_:function(){var content=tr.b.units.Time.currentDisplayUnit.format(this.timestamp_);this.shadowRoot.textContent=content;}});'use strict';Polymer('tr-c-a-analysis-link',{ready:function(){this.addEventListener('click',this.onClicked_.bind(this));this.selection_=undefined;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.textContent=selection.userFriendlyName;},setSelectionAndContent:function(selection,opt_textContent){this.selection_=selection;if(opt_textContent)
+this.textContent=opt_textContent;},onClicked_:function(){if(!this.selection_)
+return;var event=new tr.c.RequestSelectionChangeEvent();if(typeof this.selection_==='function')
+event.selection=this.selection_();else
+event.selection=this.selection_;this.dispatchEvent(event);}});'use strict';tr.exportTo('tr.b.units',function(){function SizeInBytes(numBytes){this.numBytes=numBytes;};SizeInBytes.prototype={toString:function(){return this.numBytes.toFixed(0)+' bytes';}};return{SizeInBytes:SizeInBytes};});'use strict';Polymer('tr-b-u-size-in-bytes-span',{ready:function(){this.$.content.textContent=String.fromCharCode(9888);this.numBytes_=undefined;},get numBytes(){return this.numBytes_;},set numBytes(numBytesOrSizeInBytes){if(numBytesOrSizeInBytes instanceof tr.b.units.SizeInBytes)
+this.numBytes_=numBytesOrSizeInBytes.numBytes;else
+this.numBytes_=numBytesOrSizeInBytes;var numBytes=this.numBytes;var signPrefix='';if(numBytes<0){signPrefix='-';numBytes=-numBytes;}
+var unitPrefixes=['','Ki','Mi','Gi','Ti'];var i=0;while(numBytes>=1024&&i<unitPrefixes.length-1){numBytes/=1024;i++;}
+var sizeString=signPrefix+numBytes.toFixed(1)+' '+unitPrefixes[i]+'B';this.$.content.textContent=sizeString;},get stringContent(){return this.$.content.textContent;}});'use strict';(function(){var RIGHT_ARROW=String.fromCharCode(0x25b6);var UNSORTED_ARROW=String.fromCharCode(0x25BF);var ASCENDING_ARROW=String.fromCharCode(0x25BE);var DESCENDING_ARROW=String.fromCharCode(0x25B4);var BASIC_INDENTATION=8;Polymer('tr-b-ui-table',{created:function(){this.supportsSelection_=false;this.cellSelectionMode_=false;this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;this.tableColumns_=[];this.tableRows_=[];this.tableRowsInfo_=[];this.tableFooterRows_=[];this.sortColumnIndex_=undefined;this.sortDescending_=false;this.columnsWithExpandButtons_=[];this.headerCells_=[];this.showHeader_=true;this.emptyValue_=undefined;this.subRowsPropertyName_='subRows';},ready:function(){this.$.body.addEventListener('keydown',this.onKeyDown_.bind(this),true);},clear:function(){this.supportsSelection_=false;this.cellSelectionMode_=false;this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;this.textContent='';this.tableColumns_=[];this.tableRows_=[];this.tableRowsInfo_=new WeakMap();this.tableFooterRows_=[];this.tableFooterRowsInfo_=new WeakMap();this.sortColumnIndex_=undefined;this.sortDescending_=false;this.columnsWithExpandButtons_=[];this.headerCells_=[];this.subRowsPropertyName_='subRows';},get showHeader(){return this.showHeader_;},set showHeader(showHeader){this.showHeader_=showHeader;this.scheduleRebuildHeaders_();},set subRowsPropertyName(name){this.subRowsPropertyName_=name;},get emptyValue(){return this.emptyValue_;},set emptyValue(emptyValue){var previousEmptyValue=this.emptyValue_;this.emptyValue_=emptyValue;if(this.tableRows_.length===0&&emptyValue!==previousEmptyValue)
 this.scheduleRebuildBody_();},set tableColumns(columns){var columnsWithExpandButtons=[];for(var i=0;i<columns.length;i++){if(columns[i].showExpandButtons)
 columnsWithExpandButtons.push(i);}
 if(columnsWithExpandButtons.length===0){columnsWithExpandButtons=[0];}
@@ -2556,8 +2589,8 @@
 if(i!==this.sortColumnIndex_){this.headerCells_[i].sideContent=UNSORTED_ARROW;continue;}
 this.headerCells_[i].sideContent=this.sortDescending_?DESCENDING_ARROW:ASCENDING_ARROW;}},sortRows_:function(rows){rows.sort(function(rowA,rowB){if(this.sortDescending_)
 return this.tableColumns_[this.sortColumnIndex_].cmp(rowB.userRow,rowA.userRow);return this.tableColumns_[this.sortColumnIndex_].cmp(rowA.userRow,rowB.userRow);}.bind(this));for(var i=0;i<rows.length;i++){if(rows[i].isExpanded)
-this.sortRows_(rows[i].subRows);}},generateHeaderColumns_:function(){this.headerCells_=[];this.$.head.textContent='';if(!this.showHeader_)
-return;var tr=this.appendNewElement_(this.$.head,'tr');for(var i=0;i<this.tableColumns_.length;i++){var td=this.appendNewElement_(tr,'td');var headerCell=new TracingAnalysisHeaderCell();if(this.showHeader)
+this.sortRows_(rows[i][this.subRowsPropertyName_]);}},generateHeaderColumns_:function(){this.headerCells_=[];this.$.head.textContent='';if(!this.showHeader_)
+return;var tr=this.appendNewElement_(this.$.head,'tr');for(var i=0;i<this.tableColumns_.length;i++){var td=this.appendNewElement_(tr,'td');var headerCell=document.createElement('tr-b-ui-table-header-cell');if(this.showHeader)
 headerCell.cellTitle=this.tableColumns_[i].title;else
 headerCell.cellTitle='';if(this.tableColumns_[i].cmp){td.classList.add('sensitive');headerCell.tapCallback=this.createSortCallback_(i);if(this.sortColumnIndex_===i)
 headerCell.sideContent=this.sortDescending_?DESCENDING_ARROW:ASCENDING_ARROW;else
@@ -2575,12 +2608,12 @@
 c=-c;return c;}.bind(this));}
 for(var i=0;i<userRows.length;i++){var userRow=userRows[i];var rowInfo=this.getOrCreateRowInfoFor_(rowInfoMap,userRow,parentRowInfo);var htmlNode=this.getHTMLNodeForRowInfo_(tableSection,rowInfo,rowInfoMap,indentation);if(lastAddedRow===undefined){tableSection.insertBefore(htmlNode,tableSection.firstChild);}else{var nextSiblingOfLastAdded=lastAddedRow.nextSibling;tableSection.insertBefore(htmlNode,nextSiblingOfLastAdded);}
 this.updateTabIndexForTableRowNode_(htmlNode);lastAddedRow=htmlNode;if(!rowInfo.isExpanded)
-continue;lastAddedRow=this.generateTableRowNodes_(tableSection,userRow.subRows,rowInfoMap,indentation+1,lastAddedRow,rowInfo);}
+continue;lastAddedRow=this.generateTableRowNodes_(tableSection,userRow[this.subRowsPropertyName_],rowInfoMap,indentation+1,lastAddedRow,rowInfo);}
 return lastAddedRow;},getOrCreateRowInfoFor_:function(rowInfoMap,userRow,parentRowInfo){if(rowInfoMap.has(userRow))
 return rowInfoMap.get(userRow);var rowInfo={userRow:userRow,htmlNode:undefined,isExpanded:userRow.isExpanded||false,parentRowInfo:parentRowInfo};rowInfoMap.set(userRow,rowInfo);return rowInfo;},getHTMLNodeForRowInfo_:function(tableSection,rowInfo,rowInfoMap,indentation){if(rowInfo.htmlNode)
 return rowInfo.htmlNode;var INDENT_SPACE=indentation*16;var INDENT_SPACE_NO_BUTTON=indentation*16+BASIC_INDENTATION;var tr=this.ownerDocument.createElement('tr');rowInfo.htmlNode=tr;rowInfo.indentation=indentation;tr.rowInfo=rowInfo;for(var i=0;i<this.tableColumns_.length;){var td=this.appendNewElement_(tr,'td');td.columnIndex=i;var column=this.tableColumns_[i];var value=column.value(rowInfo.userRow);var colSpan=column.colSpan?column.colSpan:1;td.style.colSpan=colSpan;if(column.textAlign){td.style.textAlign=column.textAlign;}
 if(this.doesColumnIndexSupportSelection(i))
-td.classList.add('supports-selection');if(this.columnsWithExpandButtons_.indexOf(i)!=-1){if(rowInfo.userRow.subRows&&rowInfo.userRow.subRows.length>0){td.style.paddingLeft=INDENT_SPACE+'px';var expandButton=this.appendNewElement_(td,'expand-button');expandButton.textContent=RIGHT_ARROW;if(rowInfo.isExpanded)
+td.classList.add('supports-selection');if(this.columnsWithExpandButtons_.indexOf(i)!=-1){if(rowInfo.userRow[this.subRowsPropertyName_]&&rowInfo.userRow[this.subRowsPropertyName_].length>0){td.style.paddingLeft=INDENT_SPACE+'px';var expandButton=this.appendNewElement_(td,'expand-button');expandButton.textContent=RIGHT_ARROW;if(rowInfo.isExpanded)
 expandButton.classList.add('button-expanded');}else{td.style.paddingLeft=INDENT_SPACE_NO_BUTTON+'px';}}
 if(value instanceof HTMLElement)
 td.appendChild(value);else
@@ -2592,9 +2625,9 @@
 throw new Error('woah');if(cur.parentElement===tr)
 return cur;return getTD(cur.parentElement);}
 if(this.supportsSelection_){var isAlreadySelected=false;var tdThatWasClicked=getTD(e.target);if(!this.cellSelectionMode_){isAlreadySelected=this.selectedTableRowInfo_===rowInfo;}else{isAlreadySelected=this.selectedTableRowInfo_===rowInfo;isAlreadySelected&=(this.selectedColumnIndex_===tdThatWasClicked.columnIndex);}
-if(isAlreadySelected){if(rowInfo.userRow.subRows&&rowInfo.userRow.subRows.length){this.setExpandedForUserRow_(tableSection,rowInfoMap,rowInfo.userRow,!rowInfo.isExpanded);}}else{this.didTableRowInfoGetClicked_(rowInfo,tdThatWasClicked.columnIndex);}}else{if(rowInfo.userRow.subRows&&rowInfo.userRow.subRows.length){this.setExpandedForUserRow_(tableSection,rowInfoMap,rowInfo.userRow,!rowInfo.isExpanded);}}}.bind(this));}
-return rowInfo.htmlNode;},removeSubNodes_:function(tableSection,rowInfo,rowInfoMap){if(rowInfo.userRow.subRows===undefined)
-return;for(var i=0;i<rowInfo.userRow.subRows.length;i++){var subRow=rowInfo.userRow.subRows[i];var subRowInfo=rowInfoMap.get(subRow);if(!subRowInfo)
+if(isAlreadySelected){if(rowInfo.userRow[this.subRowsPropertyName_]&&rowInfo.userRow[this.subRowsPropertyName_].length){this.setExpandedForUserRow_(tableSection,rowInfoMap,rowInfo.userRow,!rowInfo.isExpanded);}}else{this.didTableRowInfoGetClicked_(rowInfo,tdThatWasClicked.columnIndex);}}else{if(rowInfo.userRow[this.subRowsPropertyName_]&&rowInfo.userRow[this.subRowsPropertyName_].length){this.setExpandedForUserRow_(tableSection,rowInfoMap,rowInfo.userRow,!rowInfo.isExpanded);}}}.bind(this));}
+return rowInfo.htmlNode;},removeSubNodes_:function(tableSection,rowInfo,rowInfoMap){if(rowInfo.userRow[this.subRowsPropertyName_]===undefined)
+return;for(var i=0;i<rowInfo.userRow[this.subRowsPropertyName_].length;i++){var subRow=rowInfo.userRow[this.subRowsPropertyName_][i];var subRowInfo=rowInfoMap.get(subRow);if(!subRowInfo)
 continue;var subNode=subRowInfo.htmlNode;if(subNode&&subNode.parentNode===tableSection){tableSection.removeChild(subNode);this.removeSubNodes_(tableSection,subRowInfo,rowInfoMap);}}},scheduleRebuildHeaders_:function(){this.headerDirty_=true;this.scheduleRebuild_();},scheduleRebuildBody_:function(){this.bodyDirty_=true;this.scheduleRebuild_();},scheduleRebuildFooter_:function(){this.footerDirty_=true;this.scheduleRebuild_();},scheduleRebuild_:function(){if(this.rebuildPending_)
 return;this.rebuildPending_=true;setTimeout(function(){this.rebuildPending_=false;this.rebuild();}.bind(this),0);},rebuildIfNeeded_:function(){this.rebuild();},rebuild:function(){var wasBodyOrHeaderDirty=this.headerDirty_||this.bodyDirty_;if(this.headerDirty_){this.generateHeaderColumns_();this.headerDirty_=false;}
 if(this.bodyDirty_){this.$.body.textContent='';this.generateTableRowNodes_(this.$.body,this.tableRows_,this.tableRowsInfo_,0,undefined,undefined);if(this.tableRows_.length===0&&this.emptyValue_!==undefined){var tr=this.ownerDocument.createElement('tr');this.$.body.appendChild(tr);tr.classList.add('empty-row');var td=this.ownerDocument.createElement('td');tr.appendChild(td);td.colSpan=this.tableColumns_.length;var emptyValue=this.emptyValue_;if(emptyValue instanceof HTMLElement)
@@ -2608,7 +2641,7 @@
 throw new Error('Row has not been seen, must expand its parents');return this.setExpandedForUserRow_(this.$.body,this.tableRowsInfo_,userRow,expanded);},setExpandedForUserRow_:function(tableSection,rowInfoMap,userRow,expanded){this.rebuildIfNeeded_();var rowInfo=rowInfoMap.get(userRow);if(rowInfo===undefined)
 throw new Error('Row has not been seen, must expand its parents');rowInfo.isExpanded=!!expanded;if(rowInfo.htmlNode===undefined)
 return;if(rowInfo.htmlNode.parentElement!==tableSection)
-return;var expandButton=rowInfo.htmlNode.querySelector('expand-button');if(rowInfo.isExpanded){expandButton.classList.add('button-expanded');var lastAddedRow=rowInfo.htmlNode;if(rowInfo.userRow.subRows){this.generateTableRowNodes_(tableSection,rowInfo.userRow.subRows,rowInfoMap,rowInfo.indentation+1,lastAddedRow,rowInfo);}}else{expandButton.classList.remove('button-expanded');this.removeSubNodes_(tableSection,rowInfo,rowInfoMap);}
+return;var expandButton=rowInfo.htmlNode.querySelector('expand-button');if(rowInfo.isExpanded){expandButton.classList.add('button-expanded');var lastAddedRow=rowInfo.htmlNode;if(rowInfo.userRow[this.subRowsPropertyName_]){this.generateTableRowNodes_(tableSection,rowInfo.userRow[this.subRowsPropertyName_],rowInfoMap,rowInfo.indentation+1,lastAddedRow,rowInfo);}}else{expandButton.classList.remove('button-expanded');this.removeSubNodes_(tableSection,rowInfo,rowInfoMap);}
 this.maybeUpdateSelectedRow_();},get supportsSelection(){return this.supportsSelection_;},set supportsSelection(supportsSelection){this.rebuildIfNeeded_();this.supportsSelection_=!!supportsSelection;this.didSelectionStateChange_();},get cellSelectionMode(){return this.cellSelectionMode_;},set cellSelectionMode(cellSelectionMode){this.rebuildIfNeeded_();this.cellSelectionMode_=!!cellSelectionMode;this.didSelectionStateChange_();},didSelectionStateChange_:function(){if(!this.supportsSelection_){this.$.body.classList.remove('cell-selection-mode');this.$.body.classList.remove('row-selection-mode');}else if(!this.cellSelectionMode_){this.$.body.classList.remove('cell-selection-mode');this.$.body.classList.add('row-selection-mode');}else{this.$.body.classList.add('cell-selection-mode');this.$.body.classList.remove('row-selection-mode');}
 for(var i=0;i<this.$.body.children.length;i++)
 this.updateTabIndexForTableRowNode_(this.$.body.children[i]);this.maybeUpdateSelectedRow_();},maybeUpdateSelectedRow_:function(){if(this.selectedTableRowInfo_===undefined)
@@ -2631,7 +2664,7 @@
 throw new Error('nope');this.selectedColumnIndex_=i;}}else{this.selectedColumnIndex_=undefined;}
 this.updateSelectedState_();this.dispatchEvent(e);},updateTabIndexForTableRowNode_:function(row){if(this.supportsSelection_){if(!this.cellSelectionMode_){row.tabIndex=0;}else{for(var i=0;i<this.tableColumns_.length;i++){if(!this.doesColumnIndexSupportSelection(i))
 continue;row.children[i].tabIndex=0;}}}else{if(!this.cellSelectionMode_){row.removeAttribute('tabIndex');}else{for(var i=0;i<this.tableColumns_.length;i++){if(!this.doesColumnIndexSupportSelection(i))
-continue;row.children[i].removeAttribute('tabIndex');}}}},prepareToChangeSelection_:function(){var e=new Event('selection-changed',false,false);var previousSelectedRowInfo=this.selectedTableRowInfo_;if(previousSelectedRowInfo)
+continue;row.children[i].removeAttribute('tabIndex');}}}},prepareToChangeSelection_:function(){var e=new Event('selection-changed');var previousSelectedRowInfo=this.selectedTableRowInfo_;if(previousSelectedRowInfo)
 e.previousSelectedTableRow=previousSelectedRowInfo.userRow;else
 e.previousSelectedTableRow=undefined;if(this.selectedTableRowInfo_){var node=this.getSelectableNodeGivenTableRowNode_(this.selectedTableRowInfo_.htmlNode);node.removeAttribute('selected');}
 return e;},updateSelectedState_:function(){if(this.selectedTableRowInfo_===undefined)
@@ -2647,78 +2680,123 @@
 this.selectedTableRowInfo_=undefined;this.updateSelectedState_();this.dispatchEvent(e);},onKeyDown_:function(e){if(this.supportsSelection_===false)
 return;if(this.selectedTableRowInfo_===undefined)
 return;var code_to_command_names={37:'ARROW_LEFT',38:'ARROW_UP',39:'ARROW_RIGHT',40:'ARROW_DOWN'};var cmdName=code_to_command_names[e.keyCode];if(cmdName===undefined)
-return;e.stopPropagation();e.preventDefault();this.performKeyCommand_(cmdName);},performKeyCommand_:function(cmdName){this.rebuildIfNeeded_();var rowInfo=this.selectedTableRowInfo_;var htmlNode=rowInfo.htmlNode;if(cmdName==='ARROW_UP'){var prev=htmlNode.previousElementSibling;if(prev){tv.b.scrollIntoViewIfNeeded(prev);this.selectedTableRow=prev.rowInfo.userRow;this.focusSelected_();return;}
+return;e.stopPropagation();e.preventDefault();this.performKeyCommand_(cmdName);},performKeyCommand_:function(cmdName){this.rebuildIfNeeded_();var rowInfo=this.selectedTableRowInfo_;var htmlNode=rowInfo.htmlNode;if(cmdName==='ARROW_UP'){var prev=htmlNode.previousElementSibling;if(prev){tr.b.scrollIntoViewIfNeeded(prev);this.selectedTableRow=prev.rowInfo.userRow;this.focusSelected_();return;}
 return;}
-if(cmdName==='ARROW_DOWN'){var next=htmlNode.nextElementSibling;if(next){tv.b.scrollIntoViewIfNeeded(next);this.selectedTableRow=next.rowInfo.userRow;this.focusSelected_();return;}
+if(cmdName==='ARROW_DOWN'){var next=htmlNode.nextElementSibling;if(next){tr.b.scrollIntoViewIfNeeded(next);this.selectedTableRow=next.rowInfo.userRow;this.focusSelected_();return;}
 return;}
 if(cmdName==='ARROW_RIGHT'){if(this.cellSelectionMode_){var newIndex=this.selectedColumnIndex_+1;if(newIndex>=this.tableColumns_.length)
 return;if(!this.doesColumnIndexSupportSelection(newIndex))
-return;this.selectedColumnIndex=newIndex;this.focusSelected_();return;}else{if(rowInfo.userRow.subRows===undefined)
-return;if(rowInfo.userRow.subRows.length===0)
+return;this.selectedColumnIndex=newIndex;this.focusSelected_();return;}else{if(rowInfo.userRow[this.subRowsPropertyName_]===undefined)
+return;if(rowInfo.userRow[this.subRowsPropertyName_].length===0)
 return;if(!rowInfo.isExpanded)
-this.setExpandedForTableRow(rowInfo.userRow,true);this.selectedTableRow=rowInfo.userRow.subRows[0];this.focusSelected_();return;}}
+this.setExpandedForTableRow(rowInfo.userRow,true);this.selectedTableRow=rowInfo.userRow[this.subRowsPropertyName_][0];this.focusSelected_();return;}}
 if(cmdName==='ARROW_LEFT'){if(this.cellSelectionMode_){var newIndex=this.selectedColumnIndex_-1;if(newIndex<0)
 return;if(!this.doesColumnIndexSupportSelection(newIndex))
 return;this.selectedColumnIndex=newIndex;this.focusSelected_();return;}else{if(rowInfo.isExpanded){this.setExpandedForTableRow(rowInfo.userRow,false);this.focusSelected_();return;}
 var parentRowInfo=rowInfo.parentRowInfo;if(parentRowInfo){this.selectedTableRow=parentRowInfo.userRow;this.focusSelected_();return;}
 return;}}
 throw new Error('Unrecognized command');},focusSelected_:function(){if(!this.selectedTableRowInfo_)
-return;var node=this.getSelectableNodeGivenTableRowNode_(this.selectedTableRowInfo_.htmlNode);node.focus();}});})();'use strict';Polymer('tracing-analysis-header-cell',{created:function(){this.tapCallback_=undefined;this.cellTitle_='';},set cellTitle(value){this.cellTitle_=value;var titleNode;if(this.cellTitle_ instanceof Node)
+return;var node=this.getSelectableNodeGivenTableRowNode_(this.selectedTableRowInfo_.htmlNode);node.focus();}});})();'use strict';Polymer('tr-b-ui-table-header-cell',{created:function(){this.tapCallback_=undefined;this.cellTitle_='';},set cellTitle(value){this.cellTitle_=value;var titleNode;if(this.cellTitle_ instanceof Node)
 titleNode=this.cellTitle_;else
 titleNode=this.ownerDocument.createTextNode(this.cellTitle_);this.$.title.innerText='';this.$.title.appendChild(titleNode);},get cellTitle(){return this.cellTitle_;},clearSideContent:function(){this.$.side.textContent='';},set sideContent(content){this.$.side.textContent=content;},get sideContent(){return this.$.side.textContent;},set tapCallback(callback){this.style.cursor='pointer';this.tapCallback_=callback;},get tapCallback(){return this.tapCallback_;},onTap_:function(){if(this.tapCallback_)
-this.tapCallback_();}});'use strict';Polymer('tv-c-a-single-event-sub-view',{ready:function(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value:function(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
+this.tapCallback_();}});'use strict';function isTable(object){if(!(object instanceof Array)||(object.length<2))return false;for(var colName in object[0]){if(typeof colName!=='string')return false;}
+for(var i=0;i<object.length;++i){if(!(object[i]instanceof Object))return false;for(var colName in object[i]){if(i&&(object[0][colName]===undefined))return false;var cellType=typeof object[i][colName];if(cellType!=='string'&&cellType!='number')return false;}
+if(i){for(var colName in object[0]){if(object[i][colName]===undefined)return false;}}}
+return true;}
+Polymer('tr-c-a-generic-object-view',{ready:function(){this.object_=undefined;},get object(){return this.object_;},set object(object){this.object_=object;this.updateContents_();},updateContents_:function(){this.$.content.textContent='';this.appendElementsForType_('',this.object_,0,0,5,'');},appendElementsForType_:function(label,object,indent,depth,maxDepth,suffix){if(depth>maxDepth){this.appendSimpleText_(label,indent,'<recursion limit reached>',suffix);return;}
+if(object===undefined){this.appendSimpleText_(label,indent,'undefined',suffix);return;}
+if(object===null){this.appendSimpleText_(label,indent,'null',suffix);return;}
+if(!(object instanceof Object)){var type=typeof object;if(type=='string'){var objectReplaced=false;if((object[0]=='{'&&object[object.length-1]=='}')||(object[0]=='['&&object[object.length-1]==']')){try{object=JSON.parse(object);objectReplaced=true;}catch(e){}}
+if(!objectReplaced){if(object.indexOf('\n')!==-1){var lines=object.split('\n');lines.forEach(function(line,i){var text,ioff,ll,ss;if(i==0){text='"'+line;ioff=0;ll=label;ss='';}else if(i<lines.length-1){text=line;ioff=1;ll='';ss='';}else{text=line+'"';ioff=1;ll='';ss=suffix;}
+var el=this.appendSimpleText_(ll,indent+ioff*label.length+ioff,text,ss);el.style.whiteSpace='pre';return el;},this);return;}else{this.appendSimpleText_(label,indent,'"'+object+'"',suffix);return;}}
+else{}}else{return this.appendSimpleText_(label,indent,object,suffix);}}
+if(object instanceof tr.model.ObjectSnapshot){var link=document.createElement('tr-c-a-analysis-link');link.selection=new tr.c.Selection(object);this.appendElementWithLabel_(label,indent,link,suffix);return;}
+if(object instanceof tr.model.ObjectInstance){var link=document.createElement('tr-c-a-analysis-link');link.selection=new tr.c.Selection(object);this.appendElementWithLabel_(label,indent,link,suffix);return;}
+if(object instanceof tr.b.Rect){this.appendSimpleText_(label,indent,object.toString(),suffix);return;}
+if(object instanceof tr.b.units.SizeInBytes){var el=this.ownerDocument.createElement('tr-b-u-size-in-bytes-span');el.numBytes=object.numBytes;this.appendElementWithLabel_(label,indent,el,suffix);return;}
+if(object instanceof tr.b.units.TimeDuration){var el=this.ownerDocument.createElement('tr-b-u-time-duration-span');el.duration=object.duration;this.appendElementWithLabel_(label,indent,el,suffix);return;}
+if(object instanceof tr.b.units.TimeStamp){var el=this.ownerDocument.createElement('tr-b-u-time-stamp-span');el.timestamp=object.timestamp;this.appendElementWithLabel_(label,indent,el,suffix);return;}
+if(object instanceof Array){this.appendElementsForArray_(label,object,indent,depth,maxDepth,suffix);return;}
+this.appendElementsForObject_(label,object,indent,depth,maxDepth,suffix);},appendElementsForArray_:function(label,object,indent,depth,maxDepth,suffix){if(object.length==0){this.appendSimpleText_(label,indent,'[]',suffix);return;}
+if(isTable(object)){var table=document.createElement('tr-b-ui-table');var columns=[];tr.b.iterItems(object[0],function(colName){columns.push({title:colName,value:function(row){return row[colName];}});});table.tableColumns=columns;table.tableRows=object;this.appendElementWithLabel_(label,indent,table,suffix);table.rebuild();return;}
+this.appendElementsForType_(label+'[',object[0],indent,depth+1,maxDepth,object.length>1?',':']'+suffix);for(var i=1;i<object.length;i++){this.appendElementsForType_('',object[i],indent+label.length+1,depth+1,maxDepth,i<object.length-1?',':']'+suffix);}
+return;},appendElementsForObject_:function(label,object,indent,depth,maxDepth,suffix){var keys=tr.b.dictionaryKeys(object);if(keys.length==0){this.appendSimpleText_(label,indent,'{}',suffix);return;}
+this.appendElementsForType_(label+'{'+keys[0]+': ',object[keys[0]],indent,depth,maxDepth,keys.length>1?',':'}'+suffix);for(var i=1;i<keys.length;i++){this.appendElementsForType_(keys[i]+': ',object[keys[i]],indent+label.length+1,depth+1,maxDepth,i<keys.length-1?',':'}'+suffix);}},appendElementWithLabel_:function(label,indent,dataElement,suffix){var row=document.createElement('div');var indentSpan=document.createElement('span');indentSpan.style.whiteSpace='pre';for(var i=0;i<indent;i++)
+indentSpan.textContent+=' ';row.appendChild(indentSpan);var labelSpan=document.createElement('span');labelSpan.textContent=label;row.appendChild(labelSpan);row.appendChild(dataElement);var suffixSpan=document.createElement('span');suffixSpan.textContent=suffix;row.appendChild(suffixSpan);row.dataElement=dataElement;this.$.content.appendChild(row);},appendSimpleText_:function(label,indent,text,suffix){var el=this.ownerDocument.createElement('span');el.textContent=text;this.appendElementWithLabel_(label,indent,el,suffix);return el;}});'use strict';Polymer('tr-c-a-generic-object-view-with-label',{ready:function(){this.labelEl_=document.createElement('div');this.genericObjectView_=document.createElement('tr-c-a-generic-object-view');this.shadowRoot.appendChild(this.labelEl_);this.shadowRoot.appendChild(this.genericObjectView_);},get label(){return this.labelEl_.textContent;},set label(label){this.labelEl_.textContent=label;},get object(){return this.genericObjectView_.object;},set object(object){this.genericObjectView_.object=object;}});'use strict';Polymer('tr-c-a-stack-frame',{ready:function(){this.stackFrame_=undefined;},get stackFrame(){return this.stackFrame_;},set stackFrame(stackFrame){this.stackFrame_=stackFrame;this.$.ov.object=stackFrame.getUserFriendlyStackTrace();}});'use strict';Polymer('tr-c-a-single-event-sub-view',{ready:function(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value:function(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
 throw new Error('Only supports single slices');this.setSelectionWithoutErrorChecks(selection);},setSelectionWithoutErrorChecks:function(selection){this.currentSelection_=selection;this.updateContents_();},getEventRows_:function(event){var rows=[];if(event.error)
 rows.push({name:'Error',value:event.error});if(event.title)
 rows.push({name:'Title',value:event.title});if(event.category)
-rows.push({name:'Category',value:event.category});var startEl=document.createElement('tv-c-a-time-stamp');startEl.timestamp=event.start;rows.push({name:'Start',value:startEl});if(event.duration){var wallDurationEl=document.createElement('tv-c-a-time-span');wallDurationEl.duration=event.duration;rows.push({name:'Wall Duration',value:wallDurationEl});}
-if(event.cpuDuration){var cpuDurationEl=document.createElement('tv-c-a-time-span');cpuDurationEl.duration=event.cpuDuration;rows.push({name:'CPU Duration',value:cpuDurationEl});}
-if(event.subSlices!==undefined&&event.subSlices.length!==0){if(event.selfTime){var selfTimeEl=document.createElement('tv-c-a-time-span');selfTimeEl.duration=event.selfTime;rows.push({name:'Self Time',value:selfTimeEl});}
-if(event.cpuSelfTime){var cpuSelfTimeEl=document.createElement('tv-c-a-time-span');cpuSelfTimeEl.duration=event.cpuSelfTime;if(event.cpuSelfTime>event.selfTime){cpuSelfTimeEl.warning=' Note that CPU Self Time is larger than Self Time. '+'This is a known limitation of this system, which occurs '+'due to several subslices, rounding issues, and imprecise '+'time at which we get cpu- and real-time.';}
+rows.push({name:'Category',value:event.category});var startEl=document.createElement('tr-b-u-time-stamp-span');startEl.timestamp=event.start;rows.push({name:'Start',value:startEl});if(event.duration){var wallDurationEl=document.createElement('tr-b-u-time-duration-span');wallDurationEl.duration=event.duration;rows.push({name:'Wall Duration',value:wallDurationEl});}
+if(event.cpuDuration){var cpuDurationEl=document.createElement('tr-b-u-time-duration-span');cpuDurationEl.duration=event.cpuDuration;rows.push({name:'CPU Duration',value:cpuDurationEl});}
+if(event.subSlices!==undefined&&event.subSlices.length!==0){if(event.selfTime){var selfTimeEl=document.createElement('tr-b-u-time-duration-span');selfTimeEl.duration=event.selfTime;rows.push({name:'Self Time',value:selfTimeEl});}
+if(event.cpuSelfTime){var cpuSelfTimeEl=document.createElement('tr-b-u-time-duration-span');cpuSelfTimeEl.duration=event.cpuSelfTime;if(event.cpuSelfTime>event.selfTime){cpuSelfTimeEl.warning=' Note that CPU Self Time is larger than Self Time. '+'This is a known limitation of this system, which occurs '+'due to several subslices, rounding issues, and imprecise '+'time at which we get cpu- and real-time.';}
 rows.push({name:'CPU Self Time',value:cpuSelfTimeEl});}}
-if(event.durationInUserTime){var durationInUserTimeEl=document.createElement('tv-c-a-time-span');durationInUserTimeEl.duration=event.durationInUserTime;rows.push({name:'Duration (U)',value:durationInUserTimeEl});}
-function createStackFrameEl(sf){var sfEl=document.createElement('tv-c-a-stack-frame');sfEl.stackFrame=sf;return sfEl;}
+if(event.durationInUserTime){var durationInUserTimeEl=document.createElement('tr-b-u-time-duration-span');durationInUserTimeEl.duration=event.durationInUserTime;rows.push({name:'Duration (U)',value:durationInUserTimeEl});}
+function createStackFrameEl(sf){var sfEl=document.createElement('tr-c-a-stack-frame');sfEl.stackFrame=sf;return sfEl;}
 if(event.startStackFrame&&event.endStackFrame){if(event.startStackFrame===event.endStackFrame){rows.push({name:'Start+End Stack Trace',value:createStackFrameEl(event.startStackFrame)});}else{rows.push({name:'Start Stack Trace',value:createStackFrameEl(event.startStackFrame)});rows.push({name:'End Stack Trace',value:createStackFrameEl(event.endStackFrame)});}}else if(event.startStackFrame){rows.push({name:'Start Stack Trace',value:createStackFrameEl(event.startStackFrame)});}else if(event.endStackFrame){rows.push({name:'End Stack Trace',value:createStackFrameEl(event.endStackFrame)});}
-if(event.info){var descriptionEl=tv.b.ui.createDiv({textContent:event.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(event.info.docLinks){event.info.docLinks.forEach(function(linkObject){var linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;linkEl.textContent=linkObject.textContent;rows.push({name:linkObject.label,value:linkEl});});}}
-if(event.associatedAlerts.length){var alertSubRows=[];event.associatedAlerts.forEach(function(alert){var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(alert);},alert.info.description);alertSubRows.push({name:alert.title,value:linkEl});});rows.push({name:'Alerts',value:'',isExpanded:true,subRows:alertSubRows});}
+if(event.info){var descriptionEl=tr.b.ui.createDiv({textContent:event.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(event.info.docLinks){event.info.docLinks.forEach(function(linkObject){var linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;linkEl.textContent=linkObject.textContent;rows.push({name:linkObject.label,value:linkEl});});}}
+if(event.associatedAlerts.length){var alertSubRows=[];event.associatedAlerts.forEach(function(alert){var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(alert);},alert.info.description);alertSubRows.push({name:alert.title,value:linkEl});});rows.push({name:'Alerts',value:'',isExpanded:true,subRows:alertSubRows});}
 return rows;},addArgsToRows_:function(rows,args){var n=0;for(var argName in args){n+=1;}
-if(n>0){var subRows=[];for(var argName in args){var argView=document.createElement('tv-c-analysis-generic-object-view');argView.object=args[argName];subRows.push({name:argName,value:argView});}
+if(n>0){var subRows=[];for(var argName in args){var argView=document.createElement('tr-c-a-generic-object-view');argView.object=args[argName];subRows.push({name:argName,value:argView});}
 rows.push({name:'Args',value:'',isExpanded:true,subRows:subRows});}
 return rows;},updateContents_:function(){if(this.currentSelection_===undefined){this.$.table.rows=[];this.$.table.rebuild();return;}
-var event=this.currentSelection_[0];var rows=this.getEventRows_(event);this.addArgsToRows_(rows,event.args);this.$.table.tableRows=rows;this.$.table.rebuild();}});'use strict';Polymer('tv-c-a-related-flows',{ready:function(){this.inSelection_=undefined;this.outSelection_=undefined;this.internalSelection_=undefined;this.$.table.tableColumns=[{title:'Direction',value:function(row){return row.direction;},width:'150px'},{title:'Title',width:'100%',value:function(row){var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(row.event);});linkEl.appendChild(tv.b.ui.createSpan({textContent:row.event.title}));return linkEl;}}];},clearFlows:function(){this.inSelection_=undefined;this.outSelection_=undefined;this.internalSelection_=undefined;this.updateContents_();},setFlows:function(inSelection,outSelection,opt_internalSelection){this.inSelection_=inSelection;this.outSelection_=outSelection;if(opt_internalSelection)
-this.internalSelection_=opt_internalSelection;else
-this.internalSelection_=new tv.c.Selection();this.updateContents_();},updateContents_:function(){var table=this.$.table;if(this.inSelection_===undefined||this.outSelection_===undefined){table.tableRows=[];table.rebuild();return;}
-var rows=[];this.inSelection_.forEach(function(fe){rows.push({direction:'Incoming',event:fe});});this.outSelection_.forEach(function(fe){rows.push({direction:'Outgoing',event:fe});});this.internalSelection_.forEach(function(fe){rows.push({direction:'Internal',event:fe});});table.tableRows=rows;table.rebuild();}});'use strict';Polymer('tv-c-a-single-thread-slice-sub-view',{get selection(){return this.$.content.selection;},set selection(selection){this.$.content.selection=selection;var hasFlows=false;var slice;if(selection){slice=selection[0];hasFlows=slice.inFlowEvents.length!==0||slice.outFlowEvents.length!==0;}
-if(hasFlows){this.$.rflows.style.display='';this.$.rflows.setFlows(new tv.c.Selection(slice.inFlowEvents),new tv.c.Selection(slice.outFlowEvents));}else{this.$.rflows.style.display='none';this.$.rflows.clearFlows();}}});'use strict';Polymer('tv-c-a-selection-summary-table',{created:function(){this.selection_=new tv.b.Range();},ready:function(){this.$.table.showHeader=false;this.$.table.tableColumns=[{title:'Name',value:function(row){return row.title;},width:'350px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.updateContents_();},updateContents_:function(){var selection=this.selection_;var rows=[];var hasRange;if(this.selection_&&(!selection.bounds.isEmpty))
+var event=this.currentSelection_[0];var rows=this.getEventRows_(event);this.addArgsToRows_(rows,event.args);this.$.table.tableRows=rows;this.$.table.rebuild();}});'use strict';tr.exportTo('tr.c.analysis',function(){var FLOW_IN=0x1;var FLOW_OUT=0x2;var FLOW_IN_OUT=FLOW_IN|FLOW_OUT;function FlowClassifier(){this.numEvents_=0;this.eventsByGUID_={};}
+FlowClassifier.prototype={getFS_:function(event){var fs=this.eventsByGUID_[event.guid];if(fs===undefined){this.numEvents_++;fs={state:0,event:event};this.eventsByGUID_[event.guid]=fs;}
+return fs;},addInFlow:function(event){var fs=this.getFS_(event);fs.state|=FLOW_IN;return event;},addOutFlow:function(event){var fs=this.getFS_(event);fs.state|=FLOW_OUT;return event;},hasEvents:function(){return this.numEvents_>0;},get inFlowEvents(){var selection=new tr.c.Selection();for(var guid in this.eventsByGUID_){var fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN)
+selection.push(fs.event);}
+return selection;},get outFlowEvents(){var selection=new tr.c.Selection();for(var guid in this.eventsByGUID_){var fs=this.eventsByGUID_[guid];if(fs.state===FLOW_OUT)
+selection.push(fs.event);}
+return selection;},get internalFlowEvents(){var selection=new tr.c.Selection();for(var guid in this.eventsByGUID_){var fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN_OUT)
+selection.push(fs.event);}
+return selection;}};return{FlowClassifier:FlowClassifier};});'use strict';Polymer('tr-c-a-related-events',{ready:function(){this.eventGroups_=[];this.$.table.tableColumns=[{title:'Event(s)',value:function(row){return row.type;},width:'150px'},{title:'Link',width:'100%',value:function(row){var linkEl=document.createElement('tr-c-a-analysis-link');if(row.name)
+linkEl.setSelectionAndContent(row.selection,row.name);else
+linkEl.selection=row.selection;return linkEl;}}];},hasRelatedEvents:function(){return(this.eventGroups_&&this.eventGroups_.length>0);},addRelatedEvents:function(selection){this.addConnectedFlows_(selection);this.addConnectedEvents_(selection);this.updateContents_();},addConnectedFlows_:function(selection){var classifier=new tr.c.analysis.FlowClassifier();selection.forEach(function(slice){if(slice.inFlowEvents){slice.inFlowEvents.forEach(function(flow){classifier.addInFlow(flow);});}
+if(slice.outFlowEvents){slice.outFlowEvents.forEach(function(flow){classifier.addOutFlow(flow);});}});if(!classifier.hasEvents())
+return;var addToEventGroups=function(type,flowEvent){this.eventGroups_.push({type:type,selection:new tr.c.Selection(flowEvent),name:flowEvent.title});};classifier.inFlowEvents.forEach(addToEventGroups.bind(this,'Incoming flow'));classifier.outFlowEvents.forEach(addToEventGroups.bind(this,'Outgoing flow'));classifier.internalFlowEvents.forEach(addToEventGroups.bind(this,'Internal flow'));},addConnectedEvents_:function(selection){if(selection.length===1)
+this.addConnectedEventsForSlice_(selection[0]);else
+this.addConnectedEventsForSelection_(selection);},addConnectedEventsForSlice_:function(slice){var precedingEventsSelection=undefined;var followingEventsSelection=undefined;if(slice.inFlowEvents&&slice.inFlowEvents.length!==0){precedingEventsSelection=new tr.c.Selection();this.recursivelyAddConnectedEvents_(precedingEventsSelection,{},slice,function(event){return event.inFlowEvents;});this.eventGroups_.push({type:'Preceding events',selection:precedingEventsSelection});}
+if(slice.outFlowEvents&&slice.outFlowEvents.length!==0){followingEventsSelection=new tr.c.Selection();this.recursivelyAddConnectedEvents_(followingEventsSelection,{},slice,function(event){return event.outFlowEvents;});this.eventGroups_.push({type:'Following events',selection:followingEventsSelection});}
+if(precedingEventsSelection&&followingEventsSelection){var allEventsSelection=new tr.c.Selection();for(var i=0;i<precedingEventsSelection.length;++i)
+allEventsSelection.push(precedingEventsSelection[i]);for(var i=1;i<followingEventsSelection.length;++i)
+allEventsSelection.push(followingEventsSelection[i]);this.eventGroups_.push({type:'All connected events',selection:allEventsSelection});}},addConnectedEventsForSelection_:function(selection){var eventIds={};var allEventsSelection=new tr.c.Selection();selection.forEach(function(slice){this.recursivelyAddConnectedEvents_(allEventsSelection,eventIds,slice,function(event){var flows=[];if(event.inFlowEvents)
+flows=flows.concat(event.inFlowEvents);if(event.outFlowEvents)
+flows=flows.concat(event.outFlowEvents);return flows;});}.bind(this));if(allEventsSelection.length>selection.length){this.eventGroups_.push({type:'All connected events',selection:allEventsSelection});}},updateContents_:function(){var table=this.$.table;if(this.eventGroups_===undefined)
+table.tableRows=[];else
+table.tableRows=this.eventGroups_.slice();table.rebuild();},recursivelyAddConnectedEvents_:function(selection,eventIds,event,getFlows){if(!event||eventIds[event.guid])
+return;eventIds[event.guid]=true;selection.push(event);var flowEvents=getFlows(event);if(!flowEvents)
+return;for(var i=0;i<flowEvents.length;++i){selection.push(flowEvents[i]);this.recursivelyAddConnectedEvents_(selection,eventIds,flowEvents[i].startSlice,getFlows);this.recursivelyAddConnectedEvents_(selection,eventIds,flowEvents[i].endSlice,getFlows);}}});'use strict';Polymer('tr-c-a-single-thread-slice-sub-view',{get selection(){return this.$.content.selection;},set selection(selection){this.$.content.selection=selection;this.$.relatedEvents.addRelatedEvents(selection);if(this.$.relatedEvents.hasRelatedEvents())
+this.$.relatedEvents.style.display='';else
+this.$.relatedEvents.style.display='none';}});'use strict';Polymer('tr-c-a-selection-summary-table',{created:function(){this.selection_=new tr.b.Range();},ready:function(){this.$.table.showHeader=false;this.$.table.tableColumns=[{title:'Name',value:function(row){return row.title;},width:'350px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.updateContents_();},updateContents_:function(){var selection=this.selection_;var rows=[];var hasRange;if(this.selection_&&(!selection.bounds.isEmpty))
 hasRange=true;else
-hasRange=false;rows.push({title:'Selection start',value:hasRange?tv.c.analysis.createTimeStamp(selection.bounds.min):'<empty>'});rows.push({title:'Selection extent',value:hasRange?tv.c.analysis.createTimeSpan(selection.bounds.range):'<empty>'});this.$.table.tableRows=rows;this.$.table.rebuild();}});'use strict';tv.exportTo('tv.b',function(){function identity(d){return d;}
+hasRange=false;rows.push({title:'Selection start',value:hasRange?tr.b.units.createTimeStampSpan(selection.bounds.min):'<empty>'});rows.push({title:'Selection extent',value:hasRange?tr.b.units.createTimeSpan(selection.bounds.range):'<empty>'});this.$.table.tableRows=rows;this.$.table.rebuild();}});'use strict';tr.exportTo('tr.b',function(){function identity(d){return d;}
 function Statistics(){}
 Statistics.sum=function(ary,opt_func,opt_this){var func=opt_func||identity;var ret=0;for(var i=0;i<ary.length;i++)
 ret+=func.call(opt_this,ary[i],i);return ret;};Statistics.mean=function(ary,opt_func,opt_this){return Statistics.sum(ary,opt_func,opt_this)/ary.length;};Statistics.variance=function(ary,opt_func,opt_this){var func=opt_func||identity;var mean=Statistics.mean(ary,func,opt_this);var sumOfSquaredDistances=Statistics.sum(ary,function(d,i){var v=func.call(this,d,i)-mean;return v*v;},opt_this);return sumOfSquaredDistances/(ary.length-1);};Statistics.stddev=function(ary,opt_func,opt_this){return Math.sqrt(Statistics.variance(ary,opt_func,opt_this));};Statistics.max=function(ary,opt_func,opt_this){var func=opt_func||identity;var ret=-Infinity;for(var i=0;i<ary.length;i++)
 ret=Math.max(ret,func.call(opt_this,ary[i],i));return ret;};Statistics.min=function(ary,opt_func,opt_this){var func=opt_func||identity;var ret=Infinity;for(var i=0;i<ary.length;i++)
-ret=Math.min(ret,func.call(opt_this,ary[i],i));return ret;};Statistics.range=function(ary,opt_func,opt_this){var func=opt_func||identity;var ret=new tv.b.Range();for(var i=0;i<ary.length;i++)
+ret=Math.min(ret,func.call(opt_this,ary[i],i));return ret;};Statistics.range=function(ary,opt_func,opt_this){var func=opt_func||identity;var ret=new tr.b.Range();for(var i=0;i<ary.length;i++)
 ret.addValue(func.call(opt_this,ary[i],i));return ret;}
 Statistics.percentile=function(ary,percent,opt_func,opt_this){if(!(percent>=0&&percent<=1))
 throw new Error('percent must be [0,1]');var func=opt_func||identity;var tmp=new Array(ary.length);for(var i=0;i<ary.length;i++)
-tmp[i]=func.call(opt_this,ary[i],i);tmp.sort();var idx=Math.floor((ary.length-1)*percent);return tmp[idx];};return{Statistics:Statistics};});'use strict';tv.exportTo('tv.c.analysis',function(){function MultiEventSummary(title,events){this.title=title;this.duration_=undefined;this.selfTime_=undefined;this.events_=events;this.cpuTimesComputed_=false;this.cpuSelfTime_=undefined;this.cpuDuration_=undefined;this.untotallableArgs_=[];this.totalledArgs_=undefined;};MultiEventSummary.prototype={get duration(){if(this.duration_===undefined){this.duration_=tv.b.Statistics.sum(this.events_,function(event){return event.duration;});}
+tmp[i]=func.call(opt_this,ary[i],i);tmp.sort();var idx=Math.floor((ary.length-1)*percent);return tmp[idx];};return{Statistics:Statistics};});'use strict';tr.exportTo('tr.c.analysis',function(){function MultiEventSummary(title,events){this.title=title;this.duration_=undefined;this.selfTime_=undefined;this.events_=events;this.cpuTimesComputed_=false;this.cpuSelfTime_=undefined;this.cpuDuration_=undefined;this.untotallableArgs_=[];this.totalledArgs_=undefined;};MultiEventSummary.prototype={get duration(){if(this.duration_===undefined){this.duration_=tr.b.Statistics.sum(this.events_,function(event){return event.duration;});}
 return this.duration_;},get cpuSelfTime(){this.computeCpuTimesIfNeeded_();return this.cpuSelfTime_;},get cpuDuration(){this.computeCpuTimesIfNeeded_();return this.cpuDuration_;},computeCpuTimesIfNeeded_:function(){if(this.cpuTimesComputed_)
 return;this.cpuTimesComputed_=true;var cpuSelfTime=0;var cpuDuration=0;var hasCpuData=false;for(var i=0;i<this.events_.length;i++){var event=this.events_[i];if(event.cpuDuration!==undefined){cpuDuration+=event.cpuDuration;hasCpuData=true;}
 if(event.cpuSelfTime!==undefined){cpuSelfTime+=event.cpuSelfTime;hasCpuData=true;}}
 if(hasCpuData){this.cpuDuration_=cpuDuration;this.cpuSelfTime_=cpuSelfTime;}},get selfTime(){if(this.selfTime_===undefined){this.selfTime_=0;for(var i=0;i<this.events_.length;i++){if(this.events_[i].selfTime!==undefined)
 this.selfTime_+=this.events[i].selfTime;}}
-return this.selfTime_;},get events(){return this.events_;},get numEvents(){return this.events_.length;},get numAlerts(){if(this.numAlerts_===undefined){this.numAlerts_=tv.b.Statistics.sum(this.events_,function(event){return event.associatedAlerts.length;});}
+return this.selfTime_;},get events(){return this.events_;},get numEvents(){return this.events_.length;},get numAlerts(){if(this.numAlerts_===undefined){this.numAlerts_=tr.b.Statistics.sum(this.events_,function(event){return event.associatedAlerts.length;});}
 return this.numAlerts_;},get untotallableArgs(){this.updateArgsIfNeeded_();return this.untotallableArgs_;},get totalledArgs(){this.updateArgsIfNeeded_();return this.totalledArgs_;},updateArgsIfNeeded_:function(){if(this.totalledArgs_!==undefined)
 return;var untotallableArgs={};var totalledArgs={};for(var i=0;i<this.events_.length;i++){var event=this.events_[i];for(var argName in event.args){var argVal=event.args[argName];var type=typeof argVal;if(type!=='number'){untotallableArgs[argName]=true;delete totalledArgs[argName];continue;}
 if(untotallableArgs[argName]){continue;}
 if(totalledArgs[argName]===undefined)
 totalledArgs[argName]=0;totalledArgs[argName]+=argVal;}}
-this.untotallableArgs_=tv.b.dictionaryKeys(untotallableArgs);this.totalledArgs_=totalledArgs;}};return{MultiEventSummary:MultiEventSummary};});'use strict';Polymer('tv-c-a-multi-event-summary-table',{ready:function(){this.showTotals_=false;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;this.eventsByTitle_=undefined;},updateTableColumns_:function(rows){var hasCpuData=false;var hasAlerts=false;rows.forEach(function(row){if(row.cpuDuration!==undefined)
+this.untotallableArgs_=tr.b.dictionaryKeys(untotallableArgs);this.totalledArgs_=totalledArgs;}};return{MultiEventSummary:MultiEventSummary};});'use strict';Polymer('tr-c-a-multi-event-summary-table',{ready:function(){this.showTotals_=false;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;this.eventsByTitle_=undefined;},updateTableColumns_:function(rows){var hasCpuData=false;var hasAlerts=false;rows.forEach(function(row){if(row.cpuDuration!==undefined)
 hasCpuData=true;if(row.cpuSelfTime!==undefined)
 hasCpuData=true;if(row.numAlerts)
 hasAlerts=true;});var columns=[];columns.push({title:'Name',value:function(row){if(row.title==='Totals')
-return'Totals';var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(row.events);},row.title);return linkEl;},width:'350px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}});if(this.eventsHaveDuration_){columns.push({title:'Wall Duration (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.duration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.duration-rowB.duration;}});}
-if(this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Duration (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.cpuDuration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuDuration-rowB.cpuDuration;}});}
-if(this.eventsHaveSubRows_&&this.eventsHaveDuration_){columns.push({title:'Self time (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.selfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.selfTime-rowB.selfTime;}});}
-if(this.eventsHaveSubRows_&&this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Self Time (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.cpuSelfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuSelfTime-rowB.cpuSelfTime;}});}
+return'Totals';var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(row.events);},row.title);return linkEl;},width:'350px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}});if(this.eventsHaveDuration_){columns.push({title:'Wall Duration (ms)',value:function(row){return tr.b.units.createTimeSpan(row.duration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.duration-rowB.duration;}});}
+if(this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Duration (ms)',value:function(row){return tr.b.units.createTimeSpan(row.cpuDuration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuDuration-rowB.cpuDuration;}});}
+if(this.eventsHaveSubRows_&&this.eventsHaveDuration_){columns.push({title:'Self time (ms)',value:function(row){return tr.b.units.createTimeSpan(row.selfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.selfTime-rowB.selfTime;}});}
+if(this.eventsHaveSubRows_&&this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Self Time (ms)',value:function(row){return tr.b.units.createTimeSpan(row.cpuSelfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuSelfTime-rowB.cpuSelfTime;}});}
 columns.push({title:'Occurrences',value:function(row){return row.numEvents;},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.numEvents-rowB.numEvents;}});var alertsColumnIndex;if(hasAlerts){columns.push({title:'Num Alerts',value:function(row){return row.numAlerts;},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.numAlerts-rowB.numAlerts;}});alertsColumnIndex=columns.length-1;}
 var colWidthPercentage;if(columns.length==1)
 colWidthPercentage='100%';else
@@ -2732,57 +2810,49 @@
 this.eventsHaveSubRows_=config.eventsHaveSubRows;else
 this.eventsHaveSubRows_=true;this.eventsByTitle_=config.eventsByTitle;this.updateContents_();},get showTotals(){return this.showTotals_;},set showTotals(showTotals){this.showTotals_=showTotals;this.updateContents_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;this.updateContents_();},get eventsByTitle(){return this.eventsByTitle_;},set eventsByTitle(eventsByTitle){this.eventsByTitle_=eventsByTitle;this.updateContents_();},get selectionBounds(){return this.selectionBounds_;},set selectionBounds(selectionBounds){this.selectionBounds_=selectionBounds;this.updateContents_();},updateContents_:function(){var eventsByTitle;if(this.eventsByTitle_!==undefined)
 eventsByTitle=this.eventsByTitle_;else
-eventsByTitle=[];var allEvents=[];var rows=[];tv.b.iterItems(eventsByTitle,function(title,eventsOfSingleTitle){allEvents.push.apply(allEvents,eventsOfSingleTitle);var row=new tv.c.analysis.MultiEventSummary(title,eventsOfSingleTitle);rows.push(row);});this.updateTableColumns_(rows);this.$.table.tableRows=rows;var footerRows=[];if(this.showTotals_){footerRows.push(new tv.c.analysis.MultiEventSummary('Totals',allEvents));}
-this.$.table.footerRows=footerRows;this.$.table.rebuild();}});'use strict';Polymer('tv-c-a-multi-event-details-table',{created:function(){this.selection_=undefined;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;},ready:function(){this.initTitleTable_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;this.updateContents_();},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.updateContents_();},updateContents_:function(){var selection=this.selection_;this.updateTitleTable_();if(this.selection_===undefined){this.$.table.tableRows=[];this.$.table.tableFooterRows=[];this.$.table.rebuild();return;}
-var summary=new tv.c.analysis.MultiEventSummary('Totals',this.selection_);this.updateColumns_(summary);this.updateRows_(summary);this.$.table.rebuild();},initTitleTable_:function(){var table=this.$.titletable;table.showHeader=false;table.tableColumns=[{title:'Title',value:function(row){return row.title;},width:'350px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];},updateTitleTable_:function(){var title;if(this.selection_&&this.selection_.length)
+eventsByTitle=[];var allEvents=[];var rows=[];tr.b.iterItems(eventsByTitle,function(title,eventsOfSingleTitle){allEvents.push.apply(allEvents,eventsOfSingleTitle);var row=new tr.c.analysis.MultiEventSummary(title,eventsOfSingleTitle);rows.push(row);});this.updateTableColumns_(rows);this.$.table.tableRows=rows;var footerRows=[];if(this.showTotals_){footerRows.push(new tr.c.analysis.MultiEventSummary('Totals',allEvents));}
+this.$.table.footerRows=footerRows;this.$.table.rebuild();}});'use strict';Polymer('tr-c-a-multi-event-details-table',{created:function(){this.selection_=undefined;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;},ready:function(){this.initTitleTable_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;this.updateContents_();},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.updateContents_();},updateContents_:function(){var selection=this.selection_;this.updateTitleTable_();if(this.selection_===undefined){this.$.table.tableRows=[];this.$.table.tableFooterRows=[];this.$.table.rebuild();return;}
+var summary=new tr.c.analysis.MultiEventSummary('Totals',this.selection_);this.updateColumns_(summary);this.updateRows_(summary);this.$.table.rebuild();},initTitleTable_:function(){var table=this.$.titletable;table.showHeader=false;table.tableColumns=[{title:'Title',value:function(row){return row.title;},width:'350px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];},updateTitleTable_:function(){var title;if(this.selection_&&this.selection_.length)
 title=this.selection_[0].title;else
 title='<No selection>';var table=this.$.titletable;table.tableRows=[{title:'Title',value:title}];},updateColumns_:function(summary){var hasCpuData;if(summary.cpuDuration!==undefined)
 hasCpuData=true;if(summary.cpuSelfTime!==undefined)
 hasCpuData=true;var colWidthPercentage;if(hasCpuData)
 colWidthPercentage='20%';else
-colWidthPercentage='33.3333%';var columns=[];columns.push({title:'Start',value:function(row){if(row.__proto__===tv.c.analysis.MultiEventSummary.prototype){return row.title;}
-var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(row.event);});linkEl.appendChild(tv.c.analysis.createTimeStamp(row.start));return linkEl;},width:'350px',cmp:function(rowA,rowB){return rowA.start-rowB.start;}});if(this.eventsHaveDuration_){columns.push({title:'Wall Duration (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.duration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.duration-rowB.duration;}});}
-if(this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Duration (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.cpuDuration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuDuration-rowB.cpuDuration;}});}
-if(this.eventsHaveSubRows_&&this.eventsHaveDuration_){columns.push({title:'Self time (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.selfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.selfTime-rowB.selfTime;}});}
-if(this.eventsHaveSubRows_&&this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Self Time (ms)',value:function(row){return tv.c.analysis.createTimeSpan(row.cpuSelfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuSelfTime-rowB.cpuSelfTime;}});}
-var argKeys=tv.b.dictionaryKeys(summary.totalledArgs);argKeys.sort();var otherKeys=summary.untotallableArgs.slice(0);otherKeys.sort();argKeys.push.apply(argKeys,otherKeys);var keysWithColumns=argKeys.slice(0,4);var keysInOtherColumn=argKeys.slice(4);keysWithColumns.forEach(function(argKey){var hasTotal=summary.totalledArgs[argKey];var colDesc={title:'Arg: '+argKey,value:function(row){if(row.__proto__!==tv.c.analysis.MultiEventSummary.prototype){var argView=document.createElement('tv-c-analysis-generic-object-view');argView.object=row.args[argKey];return argView;}
+colWidthPercentage='33.3333%';var columns=[];columns.push({title:'Start',value:function(row){if(row.__proto__===tr.c.analysis.MultiEventSummary.prototype){return row.title;}
+var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(row.event);});linkEl.appendChild(tr.b.units.createTimeStampSpan(row.start));return linkEl;},width:'350px',cmp:function(rowA,rowB){return rowA.start-rowB.start;}});if(this.eventsHaveDuration_){columns.push({title:'Wall Duration (ms)',value:function(row){return tr.b.units.createTimeSpan(row.duration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.duration-rowB.duration;}});}
+if(this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Duration (ms)',value:function(row){return tr.b.units.createTimeSpan(row.cpuDuration);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuDuration-rowB.cpuDuration;}});}
+if(this.eventsHaveSubRows_&&this.eventsHaveDuration_){columns.push({title:'Self time (ms)',value:function(row){return tr.b.units.createTimeSpan(row.selfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.selfTime-rowB.selfTime;}});}
+if(this.eventsHaveSubRows_&&this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Self Time (ms)',value:function(row){return tr.b.units.createTimeSpan(row.cpuSelfTime);},width:'<upated further down>',cmp:function(rowA,rowB){return rowA.cpuSelfTime-rowB.cpuSelfTime;}});}
+var argKeys=tr.b.dictionaryKeys(summary.totalledArgs);argKeys.sort();var otherKeys=summary.untotallableArgs.slice(0);otherKeys.sort();argKeys.push.apply(argKeys,otherKeys);var keysWithColumns=argKeys.slice(0,4);var keysInOtherColumn=argKeys.slice(4);keysWithColumns.forEach(function(argKey){var hasTotal=summary.totalledArgs[argKey];var colDesc={title:'Arg: '+argKey,value:function(row){if(row.__proto__!==tr.c.analysis.MultiEventSummary.prototype){var argView=document.createElement('tr-c-a-generic-object-view');argView.object=row.args[argKey];return argView;}
 if(hasTotal)
 return row.totalledArgs[argKey];return'';},width:'<upated further down>'};if(hasTotal){colDesc.cmp=function(rowA,rowB){return rowA.args[argKey]-rowB.args[argKey];}}
-columns.push(colDesc);});if(keysInOtherColumn.length){columns.push({title:'Other Args',value:function(row){if(row.__proto__===tv.c.analysis.MultiEventSummary.prototype)
-return'';var argView=document.createElement('tv-c-analysis-generic-object-view');var obj={};for(var i=0;i<keysInOtherColumn.length;i++)
+columns.push(colDesc);});if(keysInOtherColumn.length){columns.push({title:'Other Args',value:function(row){if(row.__proto__===tr.c.analysis.MultiEventSummary.prototype)
+return'';var argView=document.createElement('tr-c-a-generic-object-view');var obj={};for(var i=0;i<keysInOtherColumn.length;i++)
 obj[keysInOtherColumn[i]]=row.args[keysInOtherColumn[i]];argView.object=obj;return argView;},width:'<upated further down>'});}
 var colWidthPercentage;if(columns.length==1)
 colWidthPercentage='100%';else
 colWidthPercentage=(100/(columns.length-1)).toFixed(3)+'%';for(var i=1;i<columns.length;i++)
 columns[i].width=colWidthPercentage;this.$.table.tableColumns=columns;},updateRows_:function(summary){this.$.table.sortColumnIndex=0;function Row(event){this.event=event;}
-Row.prototype={get start(){return this.event.start;},get duration(){return this.event.duration;},get cpuDuration(){return this.event.cpuDuration;},get selfTime(){return this.event.selfTime;},get cpuSelfTime(){return this.event.cpuSelfTime;},get args(){return this.event.args;}};this.$.table.tableRows=this.selection_.map(function(event){return new Row(event);});this.$.table.footerRows=[summary];}});'use strict';Polymer('tv-c-a-multi-event-sub-view',{created:function(){this.currentSelection_=undefined;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;},set selection(selection){if(selection.length<=1)
+Row.prototype={get start(){return this.event.start;},get duration(){return this.event.duration;},get cpuDuration(){return this.event.cpuDuration;},get selfTime(){return this.event.selfTime;},get cpuSelfTime(){return this.event.cpuSelfTime;},get args(){return this.event.args;}};this.$.table.tableRows=this.selection_.map(function(event){return new Row(event);});this.$.table.footerRows=[summary];}});'use strict';Polymer('tr-c-a-multi-event-sub-view',{created:function(){this.currentSelection_=undefined;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;},set selection(selection){if(selection.length<=1)
 throw new Error('Only supports multiple items');this.setSelectionWithoutErrorChecks(selection);},get selection(){return this.currentSelection_;},setSelectionWithoutErrorChecks:function(selection){this.currentSelection_=selection;this.updateContents_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;this.updateContents_();},updateContents_:function(){var selection=this.currentSelection_;this.$.content.textContent='';if(!selection)
-return;var eventsByTitle=selection.getEventsOrganizedByTitle();var numTitles=tv.b.dictionaryLength(eventsByTitle);var summaryTableEl=document.createElement('tv-c-a-multi-event-summary-table');summaryTableEl.configure({showTotals:numTitles>1,eventsByTitle:eventsByTitle,eventsHaveDuration:this.eventsHaveDuration_,eventsHaveSubRows:this.eventsHaveSubRows_});this.$.content.appendChild(summaryTableEl);var selectionSummaryTableEl=document.createElement('tv-c-a-selection-summary-table');selectionSummaryTableEl.selection=this.currentSelection_;this.$.content.appendChild(selectionSummaryTableEl);if(numTitles===1){var detailsTableEl=document.createElement('tv-c-a-multi-event-details-table');detailsTableEl.eventsHaveDuration=this.eventsHaveDuration_;detailsTableEl.eventsHaveSubRows=this.eventsHaveSubRows_;detailsTableEl.selection=selection;this.$.content.appendChild(detailsTableEl);}}});'use strict';tv.exportTo('tv.c.analysis',function(){var FLOW_IN=0x1;var FLOW_OUT=0x2;var FLOW_IN_OUT=FLOW_IN|FLOW_OUT;function FlowClassifier(){this.numEvents_=0;this.eventsByGUID_={};}
-FlowClassifier.prototype={getFS_:function(event){var fs=this.eventsByGUID_[event.guid];if(fs===undefined){this.numEvents_++;fs={state:0,event:event};this.eventsByGUID_[event.guid]=fs;}
-return fs;},addInFlow:function(event){var fs=this.getFS_(event);fs.state|=FLOW_IN;return event;},addOutFlow:function(event){var fs=this.getFS_(event);fs.state|=FLOW_OUT;return event;},get hasEvents(){return this.numEvents_>0;},get inFlowEvents(){var selection=new tv.c.Selection();for(var guid in this.eventsByGUID_){var fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN)
-selection.push(fs.event);}
-return selection;},get outFlowEvents(){var selection=new tv.c.Selection();for(var guid in this.eventsByGUID_){var fs=this.eventsByGUID_[guid];if(fs.state===FLOW_OUT)
-selection.push(fs.event);}
-return selection;},get internalFlowEvents(){var selection=new tv.c.Selection();for(var guid in this.eventsByGUID_){var fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN_OUT)
-selection.push(fs.event);}
-return selection;}};return{FlowClassifier:FlowClassifier};});'use strict';Polymer('tv-c-a-multi-thread-slice-sub-view',{created:function(){this.selection_=undefined;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;if(window.RasterTaskView!==undefined){if(tv.e.cc.RasterTaskSelection.supports(selection)){var ltvSelection=new tv.e.cc.RasterTaskSelection(selection);var ltv=new tv.e.cc.LayerTreeHostImplSnapshotView();ltv.objectSnapshot=ltvSelection.containingSnapshot;ltv.selection=ltvSelection;ltv.extraHighlightsByLayerId=ltvSelection.extraHighlightsByLayerId;this.$.content.textContent='';this.$.content.appendChild(ltv);this.requiresTallView_=true;return;}}
-this.$.content.textContent='';var mesv=document.createElement('tv-c-a-multi-event-sub-view');mesv.selection=selection;this.$.content.appendChild(mesv);var fc=new tv.c.analysis.FlowClassifier();selection.forEach(function(slice){slice.inFlowEvents.forEach(function(flow){fc.addInFlow(flow);});slice.outFlowEvents.forEach(function(flow){fc.addOutFlow(flow);});});if(fc.hasEvents){var rflows=document.createElement('tv-c-a-related-flows');rflows.setFlows(fc.inFlowEvents,fc.outFlowEvents,fc.internalFlowEvents);this.$.content.appendChild(rflows);}},get requiresTallView(){if(this.$.content.children.length===0)
-return false;var childTagName=this.$.content.children[0].tagName;if(childTagName==='TV-C-A-MULTI-EVENT-SUB-VIEW')
-return false;return true;}});'use strict';Polymer('tv-c-a-single-async-slice-sub-view',{getEventRows_:function(event){var rows=this.__proto__.__proto__.getEventRows_(event);rows.splice(0,0,{name:'ID',value:event.id});return rows;},get relatedEventsToHighlight(){if(!this.currentSelection_)
+return;var eventsByTitle=selection.getEventsOrganizedByTitle();var numTitles=tr.b.dictionaryLength(eventsByTitle);var summaryTableEl=document.createElement('tr-c-a-multi-event-summary-table');summaryTableEl.configure({showTotals:numTitles>1,eventsByTitle:eventsByTitle,eventsHaveDuration:this.eventsHaveDuration_,eventsHaveSubRows:this.eventsHaveSubRows_});this.$.content.appendChild(summaryTableEl);var selectionSummaryTableEl=document.createElement('tr-c-a-selection-summary-table');selectionSummaryTableEl.selection=this.currentSelection_;this.$.content.appendChild(selectionSummaryTableEl);if(numTitles===1){var detailsTableEl=document.createElement('tr-c-a-multi-event-details-table');detailsTableEl.eventsHaveDuration=this.eventsHaveDuration_;detailsTableEl.eventsHaveSubRows=this.eventsHaveSubRows_;detailsTableEl.selection=selection;this.$.content.appendChild(detailsTableEl);}}});'use strict';Polymer('tr-c-a-multi-thread-slice-sub-view',{created:function(){this.selection_=undefined;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;if(window.RasterTaskView!==undefined){if(tr.e.cc.RasterTaskSelection.supports(selection)){var ltvSelection=new tr.e.cc.RasterTaskSelection(selection);var ltv=new tr.e.cc.LayerTreeHostImplSnapshotView();ltv.objectSnapshot=ltvSelection.containingSnapshot;ltv.selection=ltvSelection;ltv.extraHighlightsByLayerId=ltvSelection.extraHighlightsByLayerId;this.$.content.textContent='';this.$.content.appendChild(ltv);this.requiresTallView_=true;return;}}
+this.$.content.textContent='';var mesv=document.createElement('tr-c-a-multi-event-sub-view');mesv.selection=selection;this.$.content.appendChild(mesv);var relatedEvents=document.createElement('tr-c-a-related-events');relatedEvents.addRelatedEvents(selection);if(relatedEvents.hasRelatedEvents()){this.$.content.appendChild(relatedEvents);}},get requiresTallView(){if(this.$.content.children.length===0)
+return false;var childTagName=this.$.content.children[0].tagName;if(childTagName==='TR-C-A-MULTI-EVENT-SUB-VIEW')
+return false;return true;}});'use strict';Polymer('tr-c-a-single-async-slice-sub-view',{getEventRows_:function(event){var rows=this.__proto__.__proto__.getEventRows_(event);rows.splice(0,0,{name:'ID',value:event.id});return rows;},get relatedEventsToHighlight(){if(!this.currentSelection_)
 return undefined;if(!this.currentSelection_[0].associatedEvents)
-return;return new tv.c.Selection(this.currentSelection_[0].associatedEvents);}});'use strict';Polymer('tv-c-a-multi-async-slice-sub-view',{get selection(){return this.$.content.selection;},set selection(selection){this.$.content.selection=selection;},get relatedEventsToHighlight(){if(!this.currentSelection_)
-return undefined;var selection=new tv.c.Selection();this.currentSelection_.forEach(function(asyncEvent){if(!asyncEvent.associatedEvents)
+return;return new tr.c.Selection(this.currentSelection_[0].associatedEvents);}});'use strict';Polymer('tr-c-a-multi-async-slice-sub-view',{get selection(){return this.$.content.selection;},set selection(selection){this.$.content.selection=selection;},get relatedEventsToHighlight(){if(!this.currentSelection_)
+return undefined;var selection=new tr.c.Selection();this.currentSelection_.forEach(function(asyncEvent){if(!asyncEvent.associatedEvents)
 return;asyncEvent.associatedEvents.forEach(function(event){selection.push(event);});});if(selection.length)
-return selection;return undefined;}});'use strict';Polymer('tv-c-single-cpu-slice-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
-throw new Error('Only supports single slices');if(!(selection[0]instanceof tv.c.trace_model.CpuSlice))
+return selection;return undefined;}});'use strict';Polymer('tr-c-a-single-cpu-slice-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
+throw new Error('Only supports single slices');if(!(selection[0]instanceof tr.model.CpuSlice))
 throw new Error('Only supports thread time slices');this.currentSelection_=selection;var cpuSlice=selection[0];var thread=cpuSlice.threadThatWasRunning;var shadowRoot=this.shadowRoot;if(thread){shadowRoot.querySelector('#process-name').textContent=thread.parent.userFriendlyName;shadowRoot.querySelector('#thread-name').textContent=thread.userFriendlyName;}else{shadowRoot.querySelector('#process-name').parentElement.style.display='none';shadowRoot.querySelector('#thread-name').textContent=cpuSlice.title;}
-shadowRoot.querySelector('#start').textContent=tv.c.analysis.tsString(cpuSlice.start);shadowRoot.querySelector('#duration').textContent=tv.c.analysis.tsString(cpuSlice.duration);var runningThreadEl=shadowRoot.querySelector('#running-thread');var timeSlice=cpuSlice.getAssociatedTimeslice();if(!timeSlice){runningThreadEl.parentElement.style.display='none';}else{var threadLink=document.createElement('tv-c-analysis-link');threadLink.selection=new tv.c.Selection(timeSlice);threadLink.textContent='Click to select';runningThreadEl.parentElement.style.display='';runningThreadEl.textContent='';runningThreadEl.appendChild(threadLink);}
-shadowRoot.querySelector('#args').object=cpuSlice.args;}});'use strict';Polymer('tv-c-a-multi-cpu-slice-sub-view',{ready:function(){this.$.content.eventsHaveSubRows=false;},get selection(){return this.$.content.selection;},set selection(selection){this.$.content.setSelectionWithoutErrorChecks(selection);}});'use strict';Polymer('tv-c-single-thread-time-slice-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
-throw new Error('Only supports single slices');if(!(selection[0]instanceof tv.c.trace_model.ThreadTimeSlice))
-throw new Error('Only supports thread time slices');this.currentSelection_=selection;var timeSlice=selection[0];var thread=timeSlice.thread;var shadowRoot=this.shadowRoot;shadowRoot.querySelector('#state').textContent=timeSlice.title;var stateColor=tv.b.ui.getColorPalette()[timeSlice.colorId];shadowRoot.querySelector('#state').style.backgroundColor=stateColor;shadowRoot.querySelector('#process-name').textContent=thread.parent.userFriendlyName;shadowRoot.querySelector('#thread-name').textContent=thread.userFriendlyName;shadowRoot.querySelector('#start').textContent=tv.c.analysis.tsString(timeSlice.start);shadowRoot.querySelector('#duration').textContent=tv.c.analysis.tsString(timeSlice.duration);var onCpuEl=shadowRoot.querySelector('#on-cpu');onCpuEl.textContent='';var runningInsteadEl=shadowRoot.querySelector('#running-instead');if(timeSlice.cpuOnWhichThreadWasRunning){runningInsteadEl.parentElement.removeChild(runningInsteadEl);var cpuLink=document.createElement('tv-c-analysis-link');cpuLink.selection=new tv.c.Selection(timeSlice.getAssociatedCpuSlice());cpuLink.textContent=timeSlice.cpuOnWhichThreadWasRunning.userFriendlyName;onCpuEl.appendChild(cpuLink);}else{onCpuEl.parentElement.removeChild(onCpuEl);var cpuSliceThatTookCpu=timeSlice.getCpuSliceThatTookCpu();if(cpuSliceThatTookCpu){var cpuLink=document.createElement('tv-c-analysis-link');cpuLink.selection=new tv.c.Selection(cpuSliceThatTookCpu);if(cpuSliceThatTookCpu.thread)
+shadowRoot.querySelector('#start').textContent=tr.b.units.tsString(cpuSlice.start);shadowRoot.querySelector('#duration').textContent=tr.b.units.tsString(cpuSlice.duration);var runningThreadEl=shadowRoot.querySelector('#running-thread');var timeSlice=cpuSlice.getAssociatedTimeslice();if(!timeSlice){runningThreadEl.parentElement.style.display='none';}else{var threadLink=document.createElement('tr-c-a-analysis-link');threadLink.selection=new tr.c.Selection(timeSlice);threadLink.textContent='Click to select';runningThreadEl.parentElement.style.display='';runningThreadEl.textContent='';runningThreadEl.appendChild(threadLink);}
+shadowRoot.querySelector('#args').object=cpuSlice.args;}});'use strict';Polymer('tr-c-a-multi-cpu-slice-sub-view',{ready:function(){this.$.content.eventsHaveSubRows=false;},get selection(){return this.$.content.selection;},set selection(selection){this.$.content.setSelectionWithoutErrorChecks(selection);}});'use strict';Polymer('tr-c-a-single-thread-time-slice-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
+throw new Error('Only supports single slices');if(!(selection[0]instanceof tr.model.ThreadTimeSlice))
+throw new Error('Only supports thread time slices');this.currentSelection_=selection;var timeSlice=selection[0];var thread=timeSlice.thread;var shadowRoot=this.shadowRoot;shadowRoot.querySelector('#state').textContent=timeSlice.title;var stateColor=tr.b.ui.getColorPalette()[timeSlice.colorId];shadowRoot.querySelector('#state').style.backgroundColor=stateColor;shadowRoot.querySelector('#process-name').textContent=thread.parent.userFriendlyName;shadowRoot.querySelector('#thread-name').textContent=thread.userFriendlyName;shadowRoot.querySelector('#start').textContent=tr.b.units.tsString(timeSlice.start);shadowRoot.querySelector('#duration').textContent=tr.b.units.tsString(timeSlice.duration);var onCpuEl=shadowRoot.querySelector('#on-cpu');onCpuEl.textContent='';var runningInsteadEl=shadowRoot.querySelector('#running-instead');if(timeSlice.cpuOnWhichThreadWasRunning){runningInsteadEl.parentElement.removeChild(runningInsteadEl);var cpuLink=document.createElement('tr-c-a-analysis-link');cpuLink.selection=new tr.c.Selection(timeSlice.getAssociatedCpuSlice());cpuLink.textContent=timeSlice.cpuOnWhichThreadWasRunning.userFriendlyName;onCpuEl.appendChild(cpuLink);}else{onCpuEl.parentElement.removeChild(onCpuEl);var cpuSliceThatTookCpu=timeSlice.getCpuSliceThatTookCpu();if(cpuSliceThatTookCpu){var cpuLink=document.createElement('tr-c-a-analysis-link');cpuLink.selection=new tr.c.Selection(cpuSliceThatTookCpu);if(cpuSliceThatTookCpu.thread)
 cpuLink.textContent=cpuSliceThatTookCpu.thread.userFriendlyName;else
 cpuLink.textContent=cpuSliceThatTookCpu.title;runningInsteadEl.appendChild(cpuLink);}else{runningInsteadEl.parentElement.removeChild(runningInsteadEl);}}
-var argsEl=shadowRoot.querySelector('#args');if(tv.b.dictionaryKeys(timeSlice.args).length>0){var argsView=document.createElement('tv-c-analysis-generic-object-view');argsView.object=timeSlice.args;argsEl.parentElement.style.display='';argsEl.textContent='';argsEl.appendChild(argsView);}else{argsEl.parentElement.style.display='none';}}});'use strict';Polymer('tv-c-a-multi-thread-time-slice-sub-view',{ready:function(){this.$.content.eventsHaveSubRows=false;},get selection(){return this.$.content.selection;},set selection(selection){this.$.content.setSelectionWithoutErrorChecks(selection);}});'use strict';Polymer('tv-c-single-instant-event-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.$.content.textContent='';var realView=document.createElement('tv-c-a-single-event-sub-view');realView.setSelectionWithoutErrorChecks(selection);this.$.content.appendChild(realView);this.currentSelection_=selection;},get selection(){return this.currentSelection_;}});'use strict';Polymer('tv-c-multi-instant-event-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.$.content.textContent='';var realView=document.createElement('tv-c-a-multi-event-sub-view');realView.eventsHaveDuration=false;realView.eventsHaveSubRows=false;this.$.content.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;}});'use strict';tv.exportTo('tv.c.analysis',function(){var AnalysisResults=tv.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('tv-c-analysis-link');function wrap(){return selectionGenerator();}
+var argsEl=shadowRoot.querySelector('#args');if(tr.b.dictionaryKeys(timeSlice.args).length>0){var argsView=document.createElement('tr-c-a-generic-object-view');argsView.object=timeSlice.args;argsEl.parentElement.style.display='';argsEl.textContent='';argsEl.appendChild(argsView);}else{argsEl.parentElement.style.display='none';}}});'use strict';Polymer('tr-c-a-multi-thread-time-slice-sub-view',{ready:function(){this.$.content.eventsHaveSubRows=false;},get selection(){return this.$.content.selection;},set selection(selection){this.$.content.setSelectionWithoutErrorChecks(selection);}});'use strict';Polymer('tr-c-a-single-instant-event-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.$.content.textContent='';var realView=document.createElement('tr-c-a-single-event-sub-view');realView.setSelectionWithoutErrorChecks(selection);this.$.content.appendChild(realView);this.currentSelection_=selection;},get selection(){return this.currentSelection_;}});'use strict';Polymer('tr-c-a-multi-instant-event-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.$.content.textContent='';var realView=document.createElement('tr-c-a-multi-event-sub-view');realView.eventsHaveDuration=false;realView.eventsHaveSubRows=false;this.$.content.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;}});'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);}
@@ -2799,165 +2869,166 @@
 var row=this.appendBodyRow(table);for(var i=0;i<table.numColumns;i++)
 this.appendTableCell_(table,row,i,' ');},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('tv-c-analysis-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,'');}
+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,'');},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,tv.c.analysis.tsString(time),opt_warning);},appendDetailsRow:function(table,start,duration,selfTime,args,opt_selectionGenerator,opt_cpuDuration,opt_inFoot){if(opt_inFoot){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,tv.c.analysis.tsString(start));labelEl.textContent='';labelEl.appendChild(this.createSelectionChangingLink(tv.c.analysis.tsString(start),opt_selectionGenerator,''));}else{this.appendTableCell(table,row,tv.c.analysis.tsString(start));}}
+var row=this.appendBodyRow(table);this.appendTableCell_(table,row,0,label);this.appendTableCell_(table,row,1,tr.b.units.tsString(time),opt_warning);},appendDetailsRow:function(table,start,duration,selfTime,args,opt_selectionGenerator,opt_cpuDuration,opt_inFoot){if(opt_inFoot){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,tv.c.analysis.tsString(duration));if(opt_cpuDuration)
-this.appendTableCell(table,row,opt_cpuDuration!=''?tv.c.analysis.tsString(opt_cpuDuration):'');if(selfTime!==null)
-this.appendTableCell(table,row,tv.c.analysis.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('tv-c-analysis-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);}}},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){tooltip='Min Duration:\u0009'+
-tv.c.analysis.tsString(opt_statistics.min)+' ms \u000DMax Duration:\u0009'+
-tv.c.analysis.tsString(opt_statistics.max)+' ms \u000DAvg Duration:\u0009'+
-tv.c.analysis.tsString(opt_statistics.avg)+' ms (\u03C3 = '+
-tv.c.analysis.tsRound(opt_statistics.avg_stddev)+')';if(opt_statistics.start){tooltip+='\u000DStart Time:\u0009'+
-tv.c.analysis.tsString(opt_statistics.start);}
+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);}}},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'+
-tv.c.analysis.tsString(opt_statistics.end);}
-if(opt_statistics.frequency&&opt_statistics.frequency_stddev){tooltip+='\u000DFrequency:\u0009'+
-tv.c.analysis.tsRound(opt_statistics.frequency)+' occurrences/s (\u03C3 = '+
-tv.c.analysis.tsRound(opt_statistics.frequency_stddev)+')';}}
+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,tv.c.analysis.tsString(opt_duration),tooltip);}}else{this.appendTableCell_(table,row,cellNum,'');}
+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,tv.c.analysis.tsString(opt_cpuDuration),tooltip);}else{this.appendTableCell_(table,row,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,tv.c.analysis.tsString(opt_selfTime),tooltip);}else{this.appendTableCell_(table,row,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,tv.c.analysis.tsString(opt_cpuSelfTime),tooltip);}else{this.appendTableCell_(table,row,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};});'use strict';(function(){var CounterSample=tv.c.trace_model.CounterSample;Polymer('tv-c-counter-sample-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){var results=new tv.c.analysis.AnalysisResults();this.appendChild(results);this.analyzeCounterSamples_(results,selection);},analyzeCounterSamples_:function(results,allSamples){var samplesByCounter={};for(var i=0;i<allSamples.length;i++){var ctr=allSamples[i].series.counter;if(!samplesByCounter[ctr.guid])
+cellNum++;}};return{AnalysisResults:AnalysisResults};});'use strict';(function(){var CounterSample=tr.model.CounterSample;Polymer('tr-c-a-counter-sample-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){var results=new tr.c.analysis.AnalysisResults();this.appendChild(results);this.analyzeCounterSamples_(results,selection);},analyzeCounterSamples_:function(results,allSamples){var samplesByCounter={};for(var i=0;i<allSamples.length;i++){var ctr=allSamples[i].series.counter;if(!samplesByCounter[ctr.guid])
 samplesByCounter[ctr.guid]=[];samplesByCounter[ctr.guid].push(allSamples[i]);}
 for(var guid in samplesByCounter){var samples=samplesByCounter[guid];var ctr=samples[0].series.counter;var timestampGroups=CounterSample.groupByTimestamp(samples);if(timestampGroups.length==1)
 this.analyzeSingleCounterTimestamp_(results,ctr,timestampGroups[0]);else
 this.analyzeMultipleCounterTimestamps_(results,ctr,timestampGroups);}},analyzeSingleCounterTimestamp_:function(results,ctr,samplesWithSameTimestamp){results.appendHeader('Selected counter:');var table=results.appendTable('analysis-counter-table',2);results.appendInfoRow(table,'Title',ctr.name);results.appendInfoRowTime(table,'Timestamp',samplesWithSameTimestamp[0].timestamp);for(var i=0;i<samplesWithSameTimestamp.length;i++){var sample=samplesWithSameTimestamp[i];results.appendInfoRow(table,sample.series.name,sample.value);}},analyzeMultipleCounterTimestamps_:function(results,ctr,samplesByTimestamp){results.appendHeader('Counter '+ctr.name);var table=results.appendTable('analysis-counter-table',2);var sampleIndices=[];for(var i=0;i<samplesByTimestamp.length;i++)
 sampleIndices.push(samplesByTimestamp[i][0].getSampleIndex());var stats=ctr.getSampleStatistics(sampleIndices);for(var i=0;i<stats.length;i++){var samples=[];for(var k=0;k<sampleIndices.length;++k)
-samples.push(ctr.getSeries(i).getSample(sampleIndices[k]).value);results.appendDataRow(table,ctr.name+': series('+ctr.getSeries(i).name+')',samples,null,null,null,samples.length,null,stats[i]);}}});})();'use strict';Polymer('tv-c-single-flow-event-sub-view',{getEventRows_:function(event){var rows=this.__proto__.__proto__.getEventRows_(event);rows.splice(0,0,{name:'ID',value:event.id});function createLinkTo(slice){var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(slice);});linkEl.textContent=slice.userFriendlyName;return linkEl;}
-rows.push({name:'From',value:createLinkTo(event.startSlice)});rows.push({name:'To',value:createLinkTo(event.endSlice)});return rows;}});'use strict';Polymer('tv-c-multi-flow-event-sub-view',{ready:function(){this.$.content.eventsHaveDuration=false;this.$.content.eventsHaveSubRows=false;},set selection(selection){this.$.content.selection=selection;},get selection(){return this.$.content.selection;}});'use strict';tv.exportTo('tv.c.analysis',function(){var ObjectInstanceView=tv.b.ui.define('object-instance-view');ObjectInstanceView.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.objectInstance_=undefined;},get requiresTallView(){return true;},set modelEvent(obj){this.objectInstance=obj;},get modelEvent(){return this.objectInstance;},get objectInstance(){return this.objectInstance_;},set objectInstance(i){this.objectInstance_=i;this.updateContents();},updateContents:function(){throw new Error('Not implemented');}};var options=new tv.b.ExtensionRegistryOptions(tv.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectInstanceView;options.defaultMetadata={showInTrackView:true};tv.b.decorateExtensionRegistry(ObjectInstanceView,options);return{ObjectInstanceView:ObjectInstanceView};});'use strict';Polymer('tv-c-single-object-instance-sub-view',{created:function(){this.currentSelection_=undefined;},get requiresTallView(){if(this.$.content.children.length===0)
+samples.push(ctr.getSeries(i).getSample(sampleIndices[k]).value);results.appendDataRow(table,ctr.name+': series('+ctr.getSeries(i).name+')',samples,null,null,null,samples.length,null,stats[i]);}}});})();'use strict';Polymer('tr-c-a-single-flow-event-sub-view',{getEventRows_:function(event){var rows=this.__proto__.__proto__.getEventRows_(event);rows.splice(0,0,{name:'ID',value:event.id});function createLinkTo(slice){var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(slice);});linkEl.textContent=slice.userFriendlyName;return linkEl;}
+rows.push({name:'From',value:createLinkTo(event.startSlice)});rows.push({name:'To',value:createLinkTo(event.endSlice)});return rows;}});'use strict';Polymer('tr-c-a-multi-flow-event-sub-view',{ready:function(){this.$.content.eventsHaveDuration=false;this.$.content.eventsHaveSubRows=false;},set selection(selection){this.$.content.selection=selection;},get selection(){return this.$.content.selection;}});'use strict';tr.exportTo('tr.c.analysis',function(){var ObjectInstanceView=tr.b.ui.define('object-instance-view');ObjectInstanceView.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.objectInstance_=undefined;},get requiresTallView(){return true;},set modelEvent(obj){this.objectInstance=obj;},get modelEvent(){return this.objectInstance;},get objectInstance(){return this.objectInstance_;},set objectInstance(i){this.objectInstance_=i;this.updateContents();},updateContents:function(){throw new Error('Not implemented');}};var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectInstanceView;options.defaultMetadata={showInTrackView:true};tr.b.decorateExtensionRegistry(ObjectInstanceView,options);return{ObjectInstanceView:ObjectInstanceView};});'use strict';Polymer('tr-c-a-single-object-instance-sub-view',{created:function(){this.currentSelection_=undefined;},get requiresTallView(){if(this.$.content.children.length===0)
 return false;if(this.$.content.children[0]instanceof
-tv.c.analysis.ObjectInstanceView)
+tr.c.analysis.ObjectInstanceView)
 return this.$.content.children[0].requiresTallView;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
-throw new Error('Only supports single item selections');if(!(selection[0]instanceof tv.c.trace_model.ObjectInstance))
-throw new Error('Only supports object instances');this.$.content.textContent='';this.currentSelection_=selection;var instance=selection[0];var typeInfo=tv.c.analysis.ObjectInstanceView.getTypeInfo(instance.category,instance.typeName);if(typeInfo){var customView=new typeInfo.constructor();this.$.content.appendChild(customView);customView.modelEvent=instance;}else{this.appendGenericAnalysis_(instance);}},appendGenericAnalysis_:function(instance){var html='';html+='<div class="title">'+
+throw new Error('Only supports single item selections');if(!(selection[0]instanceof tr.model.ObjectInstance))
+throw new Error('Only supports object instances');this.$.content.textContent='';this.currentSelection_=selection;var instance=selection[0];var typeInfo=tr.c.analysis.ObjectInstanceView.getTypeInfo(instance.category,instance.typeName);if(typeInfo){var customView=new typeInfo.constructor();this.$.content.appendChild(customView);customView.modelEvent=instance;}else{this.appendGenericAnalysis_(instance);}},appendGenericAnalysis_:function(instance){var html='';html+='<div class="title">'+
 instance.typeName+' '+
 instance.id+'</div>\n';html+='<table>';html+='<tr>';html+='<tr><td>creationTs:</td><td>'+
 instance.creationTs+'</td></tr>\n';if(instance.deletionTs!=Number.MAX_VALUE){html+='<tr><td>deletionTs:</td><td>'+
 instance.deletionTs+'</td></tr>\n';}else{html+='<tr><td>deletionTs:</td><td>not deleted</td></tr>\n';}
-html+='<tr><td>snapshots:</td><td id="snapshots"></td></tr>\n';html+='</table>';this.$.content.innerHTML=html;var snapshotsEl=this.$.content.querySelector('#snapshots');instance.snapshots.forEach(function(snapshot){var snapshotLink=document.createElement('tv-c-analysis-link');snapshotLink.selection=new tv.c.Selection(snapshot);snapshotsEl.appendChild(snapshotLink);});}});'use strict';tv.exportTo('tv.c.analysis',function(){var ObjectSnapshotView=tv.b.ui.define('object-snapshot-view');ObjectSnapshotView.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.objectSnapshot_=undefined;},get requiresTallView(){return true;},set modelEvent(obj){this.objectSnapshot=obj;},get modelEvent(){return this.objectSnapshot;},get objectSnapshot(){return this.objectSnapshot_;},set objectSnapshot(i){this.objectSnapshot_=i;this.updateContents();},updateContents:function(){throw new Error('Not implemented');}};var options=new tv.b.ExtensionRegistryOptions(tv.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectSnapshotView;options.defaultMetadata={showInstances:true,showInTrackView:true};tv.b.decorateExtensionRegistry(ObjectSnapshotView,options);return{ObjectSnapshotView:ObjectSnapshotView};});'use strict';Polymer('tv-c-single-object-snapshot-sub-view',{created:function(){this.currentSelection_=undefined;},get requiresTallView(){if(this.children.length===0)
-return false;if(this.children[0]instanceof tv.c.analysis.ObjectSnapshotView)
+html+='<tr><td>snapshots:</td><td id="snapshots"></td></tr>\n';html+='</table>';this.$.content.innerHTML=html;var snapshotsEl=this.$.content.querySelector('#snapshots');instance.snapshots.forEach(function(snapshot){var snapshotLink=document.createElement('tr-c-a-analysis-link');snapshotLink.selection=new tr.c.Selection(snapshot);snapshotsEl.appendChild(snapshotLink);});}});'use strict';tr.exportTo('tr.c.analysis',function(){var ObjectSnapshotView=tr.b.ui.define('object-snapshot-view');ObjectSnapshotView.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.objectSnapshot_=undefined;},get requiresTallView(){return true;},set modelEvent(obj){this.objectSnapshot=obj;},get modelEvent(){return this.objectSnapshot;},get objectSnapshot(){return this.objectSnapshot_;},set objectSnapshot(i){this.objectSnapshot_=i;this.updateContents();},updateContents:function(){throw new Error('Not implemented');}};var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectSnapshotView;options.defaultMetadata={showInstances:true,showInTrackView:true};tr.b.decorateExtensionRegistry(ObjectSnapshotView,options);return{ObjectSnapshotView:ObjectSnapshotView};});'use strict';Polymer('tr-c-a-single-object-snapshot-sub-view',{created:function(){this.currentSelection_=undefined;},get requiresTallView(){if(this.children.length===0)
+return false;if(this.children[0]instanceof tr.c.analysis.ObjectSnapshotView)
 return this.children[0].requiresTallView;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1)
-throw new Error('Only supports single item selections');if(!(selection[0]instanceof tv.c.trace_model.ObjectSnapshot))
-throw new Error('Only supports object instances');this.textContent='';this.currentSelection_=selection;var snapshot=selection[0];var typeInfo=tv.c.analysis.ObjectSnapshotView.getTypeInfo(snapshot.objectInstance.category,snapshot.objectInstance.typeName);if(typeInfo){var customView=new typeInfo.constructor();this.appendChild(customView);customView.modelEvent=snapshot;}else{this.appendGenericAnalysis_(snapshot);}},appendGenericAnalysis_:function(snapshot){var instance=snapshot.objectInstance;var html='';html+='<div class="title">Snapshot of <a id="instance-link"></a> @ '+
-tv.c.analysis.tsString(snapshot.ts)+'</div>\n';html+='<table>';html+='<tr>';html+='<tr><td>args:</td><td id="args"></td></tr>\n';html+='</table>';this.innerHTML=html;var instanceLinkEl=document.createElement('tv-c-analysis-link');instanceLinkEl.selection=new tv.c.Selection(instance);var tmp=this.querySelector('#instance-link');tmp.parentElement.replaceChild(instanceLinkEl,tmp);var argsEl=this.querySelector('#args');argsEl.textContent='';var objectView=document.createElement('tv-c-analysis-generic-object-view');objectView.object=snapshot.args;argsEl.appendChild(objectView);}});'use strict';Polymer('tv-c-multi-object-sub-view',{created:function(){this.currentSelection_=undefined;},ready:function(){this.$.content.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;var objectEvents=tv.b.asArray(selection).sort(tv.b.Range.compareByMinTimes);var table=this.$.content;table.tableColumns=[{title:'First',value:function(event){if(event instanceof tv.c.trace_model.ObjectSnapshot)
-return tv.c.analysis.createTimeStamp(event.ts);var spanEl=document.createElement('span');spanEl.appendChild(tv.c.analysis.createTimeStamp(event.creationTs));spanEl.appendChild(tv.b.ui.createSpan({textContent:'-',marginLeft:'4px',marginRight:'4px'}));if(event.deletionTs!=Number.MAX_VALUE){spanEl.appendChild(tv.c.analysis.createTimeStamp(event.deletionTs));}
-return spanEl;},width:'200px'},{title:'Second',value:function(event){var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(event);},event.userFriendlyName);return linkEl;},width:'100%'}];table.tableRows=objectEvents;table.rebuild();}});'use strict';Polymer('tv-c-single-sample-sub-view',{created:function(){this.currentSelection_=undefined;},ready:function(){this.$.content.tableColumns=[{title:'FirstColumn',value:function(row){return row.title;},width:'250px'},{title:'SecondColumn',value:function(row){return row.value;},width:'100%'}];this.$.content.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;if(this.currentSelection_===undefined){this.$.content.tableRows=[];return;}
-var sample=this.currentSelection_[0];var table=this.$.content;var rows=[];rows.push({title:'Title',value:sample.title});rows.push({title:'Sample time',value:tv.c.analysis.createTimeStamp(sample.start)});var sfEl=document.createElement('tv-c-a-stack-frame');sfEl.stackFrame=sample.leafStackFrame;rows.push({title:'Stack trace',value:sfEl});table.tableRows=rows;table.rebuild();}});'use strict';Polymer('tv-c-multi-sample-sub-view',{created:function(){this.currentSelection_=undefined;},get requiresTallView(){return true;},set selection(selection){this.$.content.textContent='';this.currentSelection_=selection;if(tv.isDefined('tv.e.analysis.SamplingSummaryPanel')){var panel=new tv.e.analysis.SamplingSummaryPanel();this.$.content.appendChild(panel);panel.selection=selection;}else{this.$.content.textContent='SamplingSummaryPanel not installed. :(';}},get selection(){return this.currentSelection_;}});'use strict';Polymer('tv-c-single-interaction-record-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.textContent='';var realView=document.createElement('tv-c-a-single-event-sub-view');this.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get relatedEventsToHighlight(){if(!this.currentSelection_)
-return undefined;return new tv.c.Selection(this.currentSelection_[0].associatedEvents);}});'use strict';Polymer('tv-c-multi-interaction-record-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.currentSelection_=selection;this.textContent='';var realView=document.createElement('tv-c-a-multi-event-sub-view');this.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;},get relatedEventsToHighlight(){if(!this.currentSelection_)
-return undefined;var selection=new tv.c.Selection();this.currentSelection_.forEach(function(ir){ir.associatedEvents.forEach(function(event){selection.push(event);});});return selection;}});'use strict';Polymer('tv-c-a-alert-sub-view',{ready:function(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value:function(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},getRowsForSingleAlert_:function(alert){var rows=[];for(var argName in alert.args){var argView=document.createElement('tv-c-analysis-generic-object-view');argView.object=alert.args[argName];rows.push({name:argName,value:argView});}
-if(alert.associatedEvents.length){alert.associatedEvents.forEach(function(event,i){var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(event);},event.title);var valueString='';if(event instanceof tv.c.trace_model.TimedEvent)
+throw new Error('Only supports single item selections');if(!(selection[0]instanceof tr.model.ObjectSnapshot))
+throw new Error('Only supports object instances');this.textContent='';this.currentSelection_=selection;var snapshot=selection[0];var typeInfo=tr.c.analysis.ObjectSnapshotView.getTypeInfo(snapshot.objectInstance.category,snapshot.objectInstance.typeName);if(typeInfo){var customView=new typeInfo.constructor();this.appendChild(customView);customView.modelEvent=snapshot;}else{this.appendGenericAnalysis_(snapshot);}},appendGenericAnalysis_:function(snapshot){var instance=snapshot.objectInstance;var html='';html+='<div class="title">Snapshot of <a id="instance-link"></a> @ '+
+tr.b.units.tsString(snapshot.ts)+'</div>\n';html+='<table>';html+='<tr>';html+='<tr><td>args:</td><td id="args"></td></tr>\n';html+='</table>';this.innerHTML=html;var instanceLinkEl=document.createElement('tr-c-a-analysis-link');instanceLinkEl.selection=new tr.c.Selection(instance);var tmp=this.querySelector('#instance-link');tmp.parentElement.replaceChild(instanceLinkEl,tmp);var argsEl=this.querySelector('#args');argsEl.textContent='';var objectView=document.createElement('tr-c-a-generic-object-view');objectView.object=snapshot.args;argsEl.appendChild(objectView);}});'use strict';Polymer('tr-c-a-multi-object-sub-view',{created:function(){this.currentSelection_=undefined;},ready:function(){this.$.content.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;var objectEvents=tr.b.asArray(selection).sort(tr.b.Range.compareByMinTimes);var table=this.$.content;table.tableColumns=[{title:'First',value:function(event){if(event instanceof tr.model.ObjectSnapshot)
+return tr.b.units.createTimeStampSpan(event.ts);var spanEl=document.createElement('span');spanEl.appendChild(tr.b.units.createTimeStampSpan(event.creationTs));spanEl.appendChild(tr.b.ui.createSpan({textContent:'-',marginLeft:'4px',marginRight:'4px'}));if(event.deletionTs!=Number.MAX_VALUE){spanEl.appendChild(tr.b.units.createTimeStampSpan(event.deletionTs));}
+return spanEl;},width:'200px'},{title:'Second',value:function(event){var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(event);},event.userFriendlyName);return linkEl;},width:'100%'}];table.tableRows=objectEvents;table.rebuild();}});'use strict';Polymer('tr-c-a-single-sample-sub-view',{created:function(){this.currentSelection_=undefined;},ready:function(){this.$.content.tableColumns=[{title:'FirstColumn',value:function(row){return row.title;},width:'250px'},{title:'SecondColumn',value:function(row){return row.value;},width:'100%'}];this.$.content.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;if(this.currentSelection_===undefined){this.$.content.tableRows=[];return;}
+var sample=this.currentSelection_[0];var table=this.$.content;var rows=[];rows.push({title:'Title',value:sample.title});rows.push({title:'Sample time',value:tr.b.units.createTimeStampSpan(sample.start)});var sfEl=document.createElement('tr-c-a-stack-frame');sfEl.stackFrame=sample.leafStackFrame;rows.push({title:'Stack trace',value:sfEl});table.tableRows=rows;table.rebuild();}});'use strict';Polymer('tr-c-a-multi-sample-sub-view',{created:function(){this.currentSelection_=undefined;},get requiresTallView(){return true;},set selection(selection){this.$.content.textContent='';this.currentSelection_=selection;if(tr.isDefined('tr.e.analysis.SamplingSummaryPanel')){var panel=new tr.e.analysis.SamplingSummaryPanel();this.$.content.appendChild(panel);panel.selection=selection;}else{this.$.content.textContent='SamplingSummaryPanel not installed. :(';}},get selection(){return this.currentSelection_;}});'use strict';Polymer('tr-c-a-single-interaction-record-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.textContent='';var realView=document.createElement('tr-c-a-single-event-sub-view');this.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get relatedEventsToHighlight(){if(!this.currentSelection_)
+return undefined;return new tr.c.Selection(this.currentSelection_[0].associatedEvents);}});'use strict';Polymer('tr-c-a-multi-interaction-record-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.currentSelection_=selection;this.textContent='';var realView=document.createElement('tr-c-a-multi-event-sub-view');this.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;},get relatedEventsToHighlight(){if(!this.currentSelection_)
+return undefined;var selection=new tr.c.Selection();this.currentSelection_.forEach(function(ir){ir.associatedEvents.forEach(function(event){selection.push(event);});});return selection;}});'use strict';Polymer('tr-c-a-alert-sub-view',{ready:function(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value:function(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value:function(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},getRowsForSingleAlert_:function(alert){var rows=[];for(var argName in alert.args){var argView=document.createElement('tr-c-a-generic-object-view');argView.object=alert.args[argName];rows.push({name:argName,value:argView});}
+if(alert.associatedEvents.length){alert.associatedEvents.forEach(function(event,i){var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(event);},event.title);var valueString='';if(event instanceof tr.model.TimedEvent)
 valueString='took '+event.duration.toFixed(2)+'ms';rows.push({name:linkEl,value:valueString});});}
-var descriptionEl=tv.b.ui.createDiv({textContent:alert.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(alert.info.docLinks){alert.info.docLinks.forEach(function(linkObject){var linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;linkEl.textContent=linkObject.textContent;rows.push({name:linkObject.label,value:linkEl});});}
+var descriptionEl=tr.b.ui.createDiv({textContent:alert.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(alert.info.docLinks){alert.info.docLinks.forEach(function(linkObject){var linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;linkEl.textContent=linkObject.textContent;rows.push({name:linkObject.label,value:linkEl});});}
 return rows;},getRowsForAlerts_:function(alerts){if(alerts.length==1){var rows=[{name:'Alert',value:alerts[0].title}];var detailRows=this.getRowsForSingleAlert_(alerts[0]);rows.push.apply(rows,detailRows);return rows;}else{return alerts.map(function(alert){return{name:'Alert',value:alert.title,isExpanded:alerts.size<10,subRows:this.getRowsForSingleAlert_(alert)};},this);}},updateContents_:function(){if(this.currentSelection_===undefined){this.$.table.rows=[];this.$.table.rebuild();return;}
-var alerts=this.currentSelection_;this.$.table.tableRows=this.getRowsForAlerts_(alerts);this.$.table.rebuild();}});'use strict';Polymer('tv-c-single-frame-sub-view',{ready:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!=1)
-throw new Error('Only supports single frame!');this.currentSelection_=selection;this.$.asv.selection=new tv.c.Selection(selection[0].associatedAlerts);},get relatedEventsToHighlight(){if(!this.currentSelection_)
-return undefined;return new tv.c.Selection(this.currentSelection_[0].associatedEvents);}});'use strict';Polymer('tv-c-multi-frame-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.textContent='';var realView=document.createElement('tv-c-a-multi-event-sub-view');realView.eventsHaveDuration=false;realView.eventsHaveSubRows=false;this.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;},get relatedEventsToHighlight(){if(!this.currentSelection_)
-return undefined;var selection=new tv.c.Selection();this.currentSelection_.forEach(function(frameEvent){frameEvent.associatedEvents.forEach(function(event){selection.push(event);});});return selection;}});'use strict';Polymer('tv-b-color-legend',{ready:function(){var blackLargeSquareCharCode=11035;this.$.square.innerText=String.fromCharCode(blackLargeSquareCharCode);this.label_=undefined;},get label(){return this.label_;},set label(label){this.label_=label;if(this.label_===undefined){this.$.square.style.color='initial';this.$.label.innerText='';return;}
-var paletteRaw=tv.b.ui.getRawColorPalette();var colorId=tv.b.ui.getColorIdForGeneralPurposeString(this.label_);var color=tv.b.ui.colorToRGBString(paletteRaw[colorId]);this.$.square.style.color=color;this.$.label.innerText=this.label_;}});'use strict';Polymer('tv-c-a-size-span',{ready:function(){this.$.content.textContent=String.fromCharCode(9888);this.numBytes_=undefined;},get numBytes(){return this.numBytes_;},set numBytes(numBytes){this.numBytes_=numBytes;var prefixes=['','Ki','Mi','Gi','Ti'];var i=0;while(numBytes>=1024&&i<prefixes.length-1){numBytes/=1024;i++;}
-var sizeString=numBytes.toFixed(1)+' '+prefixes[i]+'B';this.$.content.textContent=sizeString;},get stringContent(){return this.$.content.textContent;}});'use strict';tv.exportTo('tv.c.analysis',function(){function MemoryColumn(title,units,cellGetter){this.title=title;this.units=units;this.cell=cellGetter;}
+var alerts=this.currentSelection_;this.$.table.tableRows=this.getRowsForAlerts_(alerts);this.$.table.rebuild();}});'use strict';Polymer('tr-c-a-single-frame-sub-view',{ready:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!=1)
+throw new Error('Only supports single frame!');this.currentSelection_=selection;this.$.asv.selection=new tr.c.Selection(selection[0].associatedAlerts);},get relatedEventsToHighlight(){if(!this.currentSelection_)
+return undefined;return new tr.c.Selection(this.currentSelection_[0].associatedEvents);}});'use strict';Polymer('tr-c-a-multi-frame-sub-view',{created:function(){this.currentSelection_=undefined;},set selection(selection){this.textContent='';var realView=document.createElement('tr-c-a-multi-event-sub-view');realView.eventsHaveDuration=false;realView.eventsHaveSubRows=false;this.appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;},get relatedEventsToHighlight(){if(!this.currentSelection_)
+return undefined;var selection=new tr.c.Selection();this.currentSelection_.forEach(function(frameEvent){frameEvent.associatedEvents.forEach(function(event){selection.push(event);});});return selection;}});'use strict';Polymer('tr-b-ui-color-legend',{ready:function(){var blackSquareCharCode=9632;this.$.square.innerText=String.fromCharCode(blackSquareCharCode);this.label_=undefined;},get label(){return this.label_;},set label(label){this.label_=label;if(this.label_===undefined){this.$.square.style.color='initial';this.$.label.innerText='';return;}
+var paletteRaw=tr.b.ui.getRawColorPalette();var colorId=tr.b.ui.getColorIdForGeneralPurposeString(this.label_);var color=tr.b.ui.colorToRGBString(paletteRaw[colorId]);this.$.square.style.color=color;this.$.label.innerText=this.label_;}});'use strict';tr.exportTo('tr.c.analysis',function(){function MemoryColumn(name,title,units,cellGetter){this.name=name;this.title=title;this.units=units;this.cell=cellGetter;}
 MemoryColumn.fromRows=function(rows,cellKey,opt_titleBuilder){var columnTraits={};function gatherTraits(row){if(row===undefined)
-return;var attrCells=row[cellKey];tv.b.iterItems(attrCells,function(attrName,attrCell){if(attrCell===undefined)
+return;var attrCells=row[cellKey];tr.b.iterItems(attrCells,function(attrName,attrCell){if(attrCell===undefined)
 return;var attrValue=attrCell.attr;if(attrValue===undefined)
 return;var existingTraits=columnTraits[attrName];if(existingTraits===undefined){columnTraits[attrName]={constructor:attrValue.constructor,units:attrValue.units};return;}
-if(existingTraits.constructor!==attrValue.constructor||existingTraits.units!==attrValue.units){existingTraits.constructor=tv.c.trace_model.UnknownAttribute;existingTraits.units=undefined;}});if(row.subRows!==undefined)
-row.subRows.forEach(gatherTraits);};rows.forEach(gatherTraits);var titleBuilder=opt_titleBuilder||tv.b.identity;var columns=[];tv.b.iterItems(columnTraits,function(columnName,columnTraits){var cellGetter=fieldGetter(cellKey,columnName);var title=titleBuilder(columnName);columns.push(MemoryColumn.fromAttributeTraits(title,columnTraits,cellGetter));});return columns;};MemoryColumn.fromAttributeTraits=function(title,traits,cellGetter){var constructor;if(traits.constructor===tv.c.trace_model.ScalarAttribute)
+if(existingTraits.constructor!==attrValue.constructor||existingTraits.units!==attrValue.units){existingTraits.constructor=tr.model.UnknownAttribute;existingTraits.units=undefined;}});if(row.subRows!==undefined)
+row.subRows.forEach(gatherTraits);};rows.forEach(gatherTraits);var titleBuilder=opt_titleBuilder||tr.b.identity;var columns=[];tr.b.iterItems(columnTraits,function(columnName,columnTraits){var cellGetter=fieldGetter(cellKey,columnName);var title=titleBuilder(columnName);columns.push(MemoryColumn.fromAttributeTraits(columnName,title,columnTraits,cellGetter));});return columns;};MemoryColumn.fromAttributeTraits=function(name,title,traits,cellGetter){var constructor;if(traits.constructor===tr.model.ScalarAttribute)
 constructor=ScalarMemoryColumn;else
-constructor=MemoryColumn;return new constructor(title,traits.units,cellGetter);};MemoryColumn.spaceEqually=function(columns){var columnWidth=(100/columns.length).toFixed(3)+'%';columns.forEach(function(column){column.width=columnWidth;});};MemoryColumn.prototype={attr:function(row){var cell=this.cell(row);if(cell===undefined)
+constructor=MemoryColumn;return new constructor(name,title,traits.units,cellGetter);};MemoryColumn.spaceEqually=function(columns){var columnWidth=(100/columns.length).toFixed(3)+'%';columns.forEach(function(column){column.width=columnWidth;});};MemoryColumn.sortByImportance=function(columns,importanceRules){var positions=columns.map(function(column,srcIndex){return{importance:column.getImportance(importanceRules),srcIndex:srcIndex,column:column};});positions.sort(function(a,b){if(a.importance===b.importance)
+return a.srcIndex-b.srcIndex;return b.importance-a.importance;});positions.forEach(function(position,dstIndex){columns[dstIndex]=position.column;});};MemoryColumn.prototype={attr:function(row){var cell=this.cell(row);if(cell===undefined)
 return undefined;return cell.attr;},value:function(row){var attr=this.attr(row);if(attr===undefined)
 return'';return this.formatDefinedAttribute(attr);},formatDefinedAttribute:function(attr){return String(attr.value);},cmp:function(rowA,rowB){var attrA=this.attr(rowA);var attrB=this.attr(rowB);if(attrA===undefined&&attrB===undefined)
 return 0;if(attrA===undefined)
 return-1;if(attrB===undefined)
-return 1;return this.compareDefinedAttributes(attrA,attrB);},compareDefinedAttributes:function(attrA,attrB){var strA=String(attrA.value);var strB=String(attrB.value);return strA.localeCompare(strB);}};function ScalarMemoryColumn(title,units,cellGetter){MemoryColumn.call(this,title,units,cellGetter);}
-ScalarMemoryColumn.prototype={__proto__:MemoryColumn.prototype,formatDefinedAttribute:function(attr){if(this.units==='bytes'){var sizeEl=document.createElement('tv-c-a-size-span');sizeEl.numBytes=attr.value;return sizeEl;}
+return 1;return this.compareDefinedAttributes(attrA,attrB);},compareDefinedAttributes:function(attrA,attrB){var strA=String(attrA.value);var strB=String(attrB.value);return strA.localeCompare(strB);},getImportance:function(importanceRules){if(importanceRules.length===0)
+return 0;for(var i=0;i<importanceRules.length;i++){var importanceRule=importanceRules[i];if(this.matchesNameCondition(importanceRule.condition))
+return importanceRule.importance;}
+var minImportance=importanceRules[0].importance;for(var i=1;i<importanceRules.length;i++){minImportance=Math.min(minImportance,importanceRules[i].importance);}
+return minImportance-1;},matchesNameCondition:function(condition){if(condition===undefined)
+return true;if(typeof(condition)==='string')
+return this.name===condition;return condition.test(this.name);}};function ScalarMemoryColumn(name,title,units,cellGetter){MemoryColumn.call(this,name,title,units,cellGetter);}
+ScalarMemoryColumn.prototype={__proto__:MemoryColumn.prototype,formatDefinedAttribute:function(attr){if(this.units==='bytes'){var sizeEl=document.createElement('tr-b-u-size-in-bytes-span');sizeEl.numBytes=attr.value;return sizeEl;}
 return MemoryColumn.prototype.formatDefinedAttribute.call(this,attr);},compareDefinedAttributes:function(attrA,attrB){return attrA.value-attrB.value;}};function MemoryCell(attr){this.attr=attr;}
-function fieldGetter(){var fields=tv.b.asArray(arguments);return function(row){var value=row;for(var i=0;i<fields.length;i++)
+function fieldGetter(){var fields=tr.b.asArray(arguments);return function(row){var value=row;for(var i=0;i<fields.length;i++)
 value=value[fields[i]];return value;};}
-return{MemoryColumn:MemoryColumn,ScalarMemoryColumn:ScalarMemoryColumn,MemoryCell:MemoryCell,fieldGetter:fieldGetter};});'use strict';Polymer('tv-c-memory-dump-allocator-details-pane',{created:function(){this.memoryAllocatorDump_=undefined;},ready:function(){this.updateContents_();},set memoryAllocatorDump(memoryAllocatorDump){this.memoryAllocatorDump_=memoryAllocatorDump;this.updateContents_();},get memoryAllocatorDump(){return this.memoryAllocatorDump_;},updateContents_:function(){this.$.contents.textContent='';if(this.memoryAllocatorDump_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory allocator dump selected';return;}
-var rows=this.createRows_();var columns=this.createColumns_(rows);var table=this.ownerDocument.createElement('tracing-analysis-nested-table');this.$.contents.appendChild(table);table.tableRows=rows;table.tableColumns=columns;table.rebuild();},createRows_:function(){var createAllocatorRow=function(allocatorDump){var cells=tv.b.mapItems(allocatorDump.attributes,function(attrName,attrValue){return new tv.c.analysis.MemoryCell(attrValue);});var row={title:allocatorDump.name,cells:cells};if(allocatorDump.children.length>0)
-row.subRows=allocatorDump.children.map(createAllocatorRow);return row;};var rows=[createAllocatorRow(this.memoryAllocatorDump_)];return rows;},createColumns_:function(rows){var titleColumn={title:'Allocator',value:function(row){return row.title;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}};var attributeColumns=tv.c.analysis.MemoryColumn.fromRows(rows,'cells');tv.c.analysis.MemoryColumn.spaceEqually(attributeColumns);var columns=[titleColumn].concat(attributeColumns);return columns;}});'use strict';tv.exportTo('tv.c.trace_model',function(){function Attribute(units){this.units=units;}
-Attribute.fromDictIfPossible=function(dict,opt_model){var typeInfo=Attribute.findTypeInfoMatching(function(typeInfo){return typeInfo.metadata.type===dict.type;});if(typeInfo===undefined){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Unknown attribute type \''+dict.type+'\'.'});}
-return UnknownAttribute.fromDict(dict,opt_model);}
-return typeInfo.constructor.fromDict(dict,opt_model);};Attribute.findCommonTraits=function(attributes,opt_model){var commonTraits;for(var i=0;i<attributes.length;i++){var attribute=attributes[i];if(attribute===undefined)
-continue;var attributeConstructor=attribute.constructor;var attributeUnits=attribute.units;if(commonTraits===undefined){commonTraits={constructor:attributeConstructor,units:attributeUnits};}else if(attributeConstructor!==commonTraits.constructor){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different types: '+
-commonTraits.constructor+' and '+attributeConstructor+'.'});}
-commonTraits={constructor:UnknownAttribute,units:undefined};break;}else if(attributeUnits!==commonTraits.units){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different units: '+commonTraits.units+' and '+attributeUnits+'.'});}
-commonTraits={constructor:UnknownAttribute,units:undefined};break;}}
-return commonTraits;};Attribute.aggregate=function(childAttributes,existingParentAttribute,opt_model){var definedChildAttributes=childAttributes.filter(function(childAttribute){return childAttribute!==undefined;});var traits=Attribute.findCommonTraits(definedChildAttributes,opt_model);if(traits===undefined)
-return existingParentAttribute;var constructor=traits.constructor;if(constructor.merge===undefined)
-return existingParentAttribute;var mergedAttribute=constructor.merge(definedChildAttributes,traits.units,opt_model);if(existingParentAttribute===undefined)
-return mergedAttribute;existingParentAttribute.useMergedAttribute(mergedAttribute,opt_model);return existingParentAttribute;}
-Attribute.fromTraceValue=function(dict,opt_model){throw new Error('Not implemented');};Attribute.prototype.useMergedAttribute=function(mergedAttribute,opt_model){if(mergedAttribute.constructor!==this.constructor){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different types: '+this.constructor+' and '+mergedAttribute.constructor+'.'});}}else if(mergedAttribute.units!==this.units){if(opt_model){opt_model.importWarning({type:'attribute_parse_error',message:'Attribute with different units: '+this.units+' and '+mergedAttribute.units+'.'});}}};var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);options.mandatoryBaseType=Attribute;tv.b.decorateExtensionRegistry(Attribute,options);Attribute.addEventListener('will-register',function(e){if(!e.typeInfo.constructor.hasOwnProperty('fromDict'))
-throw new Error('Attributes must have fromDict method');if(!e.typeInfo.metadata.type)
-throw new Error('Attributes must provide type');if(e.typeInfo.constructor.prototype.constructor!==e.typeInfo.constructor)
-throw new Error('Attribute prototypes must provide constructor.');});function ScalarAttribute(units,value){Attribute.call(this,units);this.value=value;}
-ScalarAttribute.fromDict=function(dict){return new ScalarAttribute(dict.units,parseInt(dict.value,16));};ScalarAttribute.merge=function(childAttributes,units){var sum=0;childAttributes.forEach(function(childAttribute){sum+=childAttribute.value;});return new ScalarAttribute(units,sum);}
-ScalarAttribute.prototype.__proto__=Attribute.prototype;Attribute.register(ScalarAttribute,{type:'scalar'});function StringAttribute(units,value){Attribute.call(this,units);this.value=value;}
-StringAttribute.fromDict=function(dict){return new StringAttribute(dict.units,dict.value);};Attribute.register(StringAttribute,{type:'string'});function UnknownAttribute(units,opt_value){Attribute.call(this,units,opt_value);this.value=opt_value;}
-UnknownAttribute.fromDict=function(dict){return new UnknownAttribute(dict.units);};UnknownAttribute.prototype.__proto__=Attribute.prototype;return{Attribute:Attribute,ScalarAttribute:ScalarAttribute,StringAttribute:StringAttribute,UnknownAttribute:UnknownAttribute};});'use strict';Polymer('tv-c-memory-dump-vm-regions-details-pane',{created:function(){this.vmRegions_=undefined;},ready:function(){this.updateContents_();},set vmRegions(vmRegions){this.vmRegions_=vmRegions;this.updateContents_();},get vmRegions(){return this.vmRegions_;},updateContents_:function(){this.$.contents.textContent='';if(this.vmRegions_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory maps selected';return;}
-var rows=this.createRows_();var columns=this.createColumns_(rows);var table=this.ownerDocument.createElement('tracing-analysis-nested-table');this.$.contents.appendChild(table);table.supportsSelection=true;table.tableRows=rows;table.tableColumns=columns;table.rebuild();},createRows_:function(){var use64Bits=this.vmRegions_.some(function(vmRegion){if(vmRegion.startAddress===undefined)
-return;return vmRegion.startAddress>=4294967296;});var hexPadding=use64Bits?'0000000000000000':'00000000';function hexString(address){if(address===undefined)
+var RECURSIVE_EXPANSION_MAX_SUB_ROW_COUNT=10;function expandTableRowsRecursively(table){function expandRowRecursively(row){if(row.subRows===undefined||row.subRows.length===0)
+return;if(row.subRows.length>RECURSIVE_EXPANSION_MAX_SUB_ROW_COUNT)
+return;table.setExpandedForTableRow(row,true);row.subRows.forEach(expandRowRecursively);}
+table.tableRows.forEach(expandRowRecursively);}
+return{MemoryColumn:MemoryColumn,ScalarMemoryColumn:ScalarMemoryColumn,MemoryCell:MemoryCell,fieldGetter:fieldGetter,expandTableRowsRecursively:expandTableRowsRecursively};});'use strict';(function(){var IMPORTANCE_RULES=[{condition:'size',importance:10},{condition:'outer_size',importance:9},{condition:'page_size',importance:0},{condition:/size/,importance:5},{importance:0}];Polymer('tr-c-a-memory-dump-allocator-details-pane',{created:function(){this.memoryAllocatorDump_=undefined;},ready:function(){this.updateContents_();},set memoryAllocatorDump(memoryAllocatorDump){this.memoryAllocatorDump_=memoryAllocatorDump;this.updateContents_();},get memoryAllocatorDump(){return this.memoryAllocatorDump_;},updateContents_:function(){this.$.contents.textContent='';if(this.memoryAllocatorDump_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory allocator dump selected';return;}
+var rows=this.createRows_();var columns=this.createColumns_(rows);var table=this.ownerDocument.createElement('tr-b-ui-table');this.$.contents.appendChild(table);table.supportsSelection=true;table.tableRows=rows;table.tableColumns=columns;table.rebuild();tr.c.analysis.expandTableRowsRecursively(table);},createRows_:function(){var createAllocatorRow=function(allocatorDump){var cells=tr.b.mapItems(allocatorDump.attributes,function(attrName,attrValue){return new tr.c.analysis.MemoryCell(attrValue);});var row={title:allocatorDump.name,cells:cells};if(allocatorDump.children.length>0)
+row.subRows=allocatorDump.children.map(createAllocatorRow);return row;};var rows=[createAllocatorRow(this.memoryAllocatorDump_)];return rows;},createColumns_:function(rows){var titleColumn={title:'Allocator',value:function(row){return row.title;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}};var attributeColumns=tr.c.analysis.MemoryColumn.fromRows(rows,'cells');tr.c.analysis.MemoryColumn.spaceEqually(attributeColumns);tr.c.analysis.MemoryColumn.sortByImportance(attributeColumns,IMPORTANCE_RULES);var columns=[titleColumn].concat(attributeColumns);return columns;}});})();'use strict';(function(){var CLASSIFICATION_RULES={name:'Total',children:[{name:'Android',file:/^\/dev\/ashmem/,children:[{name:'Java runtime',file:/^\/dev\/ashmem\/dalvik-.*$/,children:[{name:'Spaces',file:/\bspace/,children:[{name:'Normal',file:/(alloc)|(main)/},{name:'Large',file:/large.object/},{name:'Zygote',file:/zygote/},{name:'Non-moving',file:/non.moving/}]},{name:'Linear Alloc',file:/LinearAlloc/},{name:'Indirect Reference Table',file:/indirect.ref/},{name:'Cache',file:/jit-code-cache/},{name:'Accounting'}]},{name:'Cursor',file:/CursorWindow/},{name:'Ashmem'}]},{name:'Native heap',file:/^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|$)/},{name:'Stack',file:/^\[stack/},{name:'Files',file:/\.((((so)|(jar)|(apk)|(ttf)|(odex)|(oat)|(arg))$)|(dex))/,children:[{name:'so',file:/\.so$/},{name:'jar',file:/\.jar$/},{name:'apk',file:/\.apk$/},{name:'ttf',file:/\.ttf$/},{name:'dex',file:/\.((dex)|(odex$))/},{name:'oat',file:/\.oat$/},{name:'art',file:/\.art$/}]},{name:'Devices',file:/(^\/dev\/)|(anon_inode:dmabuf)/,children:[{name:'GPU',file:/\/((nv)|(mali)|(kgsl))/},{name:'DMA',file:/anon_inode:dmabuf/}]},{name:'Discounted tracing overhead',file:/\[discounted tracing overhead\]/}]};function createEmptyRow(rule){var row={title:rule.name,rule:rule,cells:{},subRows:[]};if(rule.children!==undefined)
+row.subRows=rule.children.map(createEmptyRow);return row;}
+function hexString(address,is64BitAddress){var hexPadding=is64BitAddress?'0000000000000000':'00000000';if(address===undefined)
 return undefined;return(hexPadding+address.toString(16)).substr(-hexPadding.length);}
-return this.vmRegions_.map(function(vmRegion){var mappedFile=vmRegion.mappedFile||'';var cells={};function addCellIfValueDefined(columnName,attrClass,units,value){if(value===undefined)
-return;var attr=new attrClass(units,value);var cell=new tv.c.analysis.MemoryCell(attr);cells[columnName]=cell;}
-addCellIfValueDefined('Start address',tv.c.trace_model.StringAttribute,'',hexString(vmRegion.startAddress));addCellIfValueDefined('Virtual size',tv.c.trace_model.ScalarAttribute,'bytes',vmRegion.sizeInBytes);addCellIfValueDefined('Protection flags',tv.c.trace_model.StringAttribute,'',vmRegion.protectionFlagsToString);addCellIfValueDefined('Proportional resident',tv.c.trace_model.ScalarAttribute,'bytes',vmRegion.byteStats.proportionalResident);addCellIfValueDefined('Private resident',tv.c.trace_model.ScalarAttribute,'bytes',vmRegion.byteStats.privateResident);addCellIfValueDefined('Shared resident',tv.c.trace_model.ScalarAttribute,'bytes',vmRegion.byteStats.sharedResident);return{mappedFile:mappedFile,cells:cells};});},createColumns_:function(rows){var titleColumn={title:'Mapped file',value:function(row){return row.mappedFile;},width:'200px',cmp:function(rowA,rowB){return rowA.mappedFile.localeCompare(rowB.mappedFile);}};var attributeColumns=tv.c.analysis.MemoryColumn.fromRows(rows,'cells');tv.c.analysis.MemoryColumn.spaceEqually(attributeColumns);var columns=[titleColumn].concat(attributeColumns);return columns;}});'use strict';Polymer('tv-c-memory-dump-overview-pane',{created:function(){this.processMemoryDumps_=undefined;},ready:function(){this.$.table.supportsSelection=true;this.$.table.cellSelectionMode=true;this.$.table.addEventListener('selection-changed',function(tableEvent){tableEvent.stopPropagation();var paneEvent=new Event('selected-memory-cell-changed',false,false);this.dispatchEvent(paneEvent);}.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.updateContents_();},get processMemoryDumps(){return this.processMemoryDumps_;},get selectedMemoryCell(){var selectedTableRow=this.$.table.selectedTableRow;if(!selectedTableRow)
+function classifyVMRegion(row,vmRegion,is64BitAddress){var rule=row.rule;if(rule===undefined||rule.children===undefined||rule.children.length===0){var mappedFile=vmRegion.mappedFile||'';var cells={};function addCellIfValueDefined(columnName,attrClass,units,value){if(value===undefined)
+return;var attr=new attrClass(units,value);var cell=new tr.c.analysis.MemoryCell(attr);cells[columnName]=cell;}
+function addBytesCellIfValueDefined(columnName,value){addCellIfValueDefined(columnName,tr.model.ScalarAttribute,'bytes',value);}
+addCellIfValueDefined('Start address',tr.model.StringAttribute,'',hexString(vmRegion.startAddress,is64BitAddress));addBytesCellIfValueDefined('Virtual size',vmRegion.sizeInBytes);addCellIfValueDefined('Protection flags',tr.model.StringAttribute,'',vmRegion.protectionFlagsToString);addBytesCellIfValueDefined('PSS',vmRegion.byteStats.proportionalResident);addBytesCellIfValueDefined('Private dirty',vmRegion.byteStats.privateDirtyResident);addBytesCellIfValueDefined('Private clean',vmRegion.byteStats.privateCleanResident);addBytesCellIfValueDefined('Shared dirty',vmRegion.byteStats.sharedDirtyResident);addBytesCellIfValueDefined('Shared clean',vmRegion.byteStats.sharedCleanResident);addBytesCellIfValueDefined('Swapped',vmRegion.byteStats.swapped);row.subRows.push({title:mappedFile,cells:cells});return;}
+function vmRegionMatchesChildRule(childRule){var fileRegExp=childRule.file;if(fileRegExp===undefined)
+return true;return fileRegExp.test(vmRegion.mappedFile);}
+var matchedChildRuleIndex=tr.b.findFirstIndexInArray(rule.children,vmRegionMatchesChildRule);if(matchedChildRuleIndex===-1){matchedChildRuleIndex=rule.children.length;if(matchedChildRuleIndex>=row.subRows.length){row.subRows.push({title:'Other',cells:{},subRows:[]});}}
+classifyVMRegion(row.subRows[matchedChildRuleIndex],vmRegion,is64BitAddress);}
+function aggregateRowCells(row){if(row.subRows===undefined)
+return;var cells={};row.subRows.forEach(function(subRow){aggregateRowCells(subRow);tr.b.iterItems(subRow.cells,function(columnName){cells[columnName]=true;});});tr.b.iterItems(cells,function(name){var childAttributes=row.subRows.map(function(subRow){var cell=subRow.cells[name];if(cell===undefined)
+return undefined;return cell.attr;},this);row.cells[name]=new tr.c.analysis.MemoryCell(tr.model.Attribute.aggregate(childAttributes));});}
+Polymer('tr-c-a-memory-dump-vm-regions-details-pane',{created:function(){this.vmRegions_=undefined;},ready:function(){this.updateContents_();},set vmRegions(vmRegions){this.vmRegions_=vmRegions;this.updateContents_();},get vmRegions(){return this.vmRegions_;},updateContents_:function(){this.$.contents.textContent='';if(this.vmRegions_===undefined){var infoText=this.ownerDocument.createElement('div');this.$.contents.appendChild(infoText);infoText.classList.add('info-text');infoText.innerText='No memory maps selected';return;}
+var rows=this.createRows_();var columns=this.createColumns_(rows);var table=this.ownerDocument.createElement('tr-b-ui-table');this.$.contents.appendChild(table);table.supportsSelection=true;table.tableRows=rows;table.tableColumns=columns;table.rebuild();tr.c.analysis.expandTableRowsRecursively(table);},createRows_:function(){var is64BitAddress=this.vmRegions_.some(function(vmRegion){if(vmRegion.startAddress===undefined)
+return;return vmRegion.startAddress>=4294967296;});var rootRow=createEmptyRow(CLASSIFICATION_RULES);this.vmRegions_.map(function(vmRegion){classifyVMRegion(rootRow,vmRegion,is64BitAddress);});aggregateRowCells(rootRow);return[rootRow];},createColumns_:function(rows){var titleColumn={title:'Mapped file',value:function(row){return row.title;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);}};var attributeColumns=tr.c.analysis.MemoryColumn.fromRows(rows,'cells');tr.c.analysis.MemoryColumn.spaceEqually(attributeColumns);var columns=[titleColumn].concat(attributeColumns);return columns;}});})();'use strict';(function(){var IMPORTANCE_RULES=[{condition:'tracing',importance:0},{importance:1}];Polymer('tr-c-a-memory-dump-overview-pane',{created:function(){this.processMemoryDumps_=undefined;},ready:function(){this.$.table.supportsSelection=true;this.$.table.cellSelectionMode=true;this.$.table.addEventListener('selection-changed',function(tableEvent){tableEvent.stopPropagation();var paneEvent=new Event('selected-memory-cell-changed');this.dispatchEvent(paneEvent);}.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.updateContents_();},get processMemoryDumps(){return this.processMemoryDumps_;},get selectedMemoryCell(){var selectedTableRow=this.$.table.selectedTableRow;if(!selectedTableRow)
 return undefined;var selectedColumnIndex=this.$.table.selectedColumnIndex;if(selectedColumnIndex===undefined)
-return undefined;var selectedColumn=this.$.table.tableColumns[selectedColumnIndex];var selectedMemoryCell=selectedColumn.cell(selectedTableRow);return selectedMemoryCell;},updateContents_:function(){var processMemoryDumps=this.processMemoryDumps_||[];var rows=processMemoryDumps.map(function(processMemoryDump){var usedMemorySizes={};var totalResident=processMemoryDump.totalResidentBytes;if(totalResident!==undefined){usedMemorySizes['Total used memory']=new tv.c.analysis.MemoryCell(new tv.c.trace_model.ScalarAttribute('bytes',totalResident));}
-var pss=processMemoryDump.mostRecentTotalProportionalResidentSizeInBytes;if(pss!==undefined){var cell=new tv.c.analysis.MemoryCell(new tv.c.trace_model.ScalarAttribute('bytes',pss));cell.buildDetailsPane=function(){var pane=document.createElement('tv-c-memory-dump-vm-regions-details-pane');pane.vmRegions=processMemoryDump.mostRecentVmRegions;return pane;}
-usedMemorySizes['Proportional used memory (mmaps)']=cell;}
-var allocatorSizes={};if(processMemoryDump.memoryAllocatorDumps!==undefined){processMemoryDump.memoryAllocatorDumps.forEach(function(dump){var cell=new tv.c.analysis.MemoryCell(dump.attributes['outer_size']);cell.buildDetailsPane=function(){var pane=document.createElement('tv-c-memory-dump-allocator-details-pane');pane.memoryAllocatorDump=dump;return pane;};allocatorSizes[dump.fullName]=cell;},this);}
-return{title:processMemoryDump.process.userFriendlyName,usedMemorySizes:usedMemorySizes,allocatorSizes:allocatorSizes};},this);this.$.table.tableRows=rows;this.updateColumns_(rows);this.$.table.rebuild();},updateColumns_:function(rows){var titleColumn={title:'Process',value:function(row){var titleEl=document.createElement('tv-b-color-legend');titleEl.label=row.title;return titleEl;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);},supportsCellSelection:false};var usedMemorySizeColumns=tv.c.analysis.MemoryColumn.fromRows(rows,'usedMemorySizes');var allocatorSizeColumns=tv.c.analysis.MemoryColumn.fromRows(rows,'allocatorSizes',function(allocatorName){var titleEl=document.createElement('tv-b-color-legend');titleEl.label=allocatorName;return titleEl;});var sizeColumns=usedMemorySizeColumns.concat(allocatorSizeColumns);tv.c.analysis.MemoryColumn.spaceEqually(sizeColumns);var columns=[titleColumn].concat(sizeColumns);this.$.table.tableColumns=columns;}});'use strict';Polymer('tv-c-memory-dump-view',{created:function(){this.processMemoryDumps_=undefined;},ready:function(){this.$.overview_pane.addEventListener('selected-memory-cell-changed',this.updateDetailsPane_.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.$.overview_pane.processMemoryDumps=this.processMemoryDumps_;this.updateDetailsPane_();},get processMemoryDumps(){return this.processMemoryDumps_;},updateDetailsPane_:function(){this.$.details_pane_container.textContent='';var selectedMemoryCell=this.$.overview_pane.selectedMemoryCell;if(!selectedMemoryCell||!selectedMemoryCell.buildDetailsPane)
-return;this.$.details_pane_container.appendChild(selectedMemoryCell.buildDetailsPane());}});'use strict';Polymer('tv-c-single-process-memory-dump-sub-view',{set selection(selection){if(selection.length!==1)
-throw new Error('Only supports a single process memory dump');if(!(selection[0]instanceof tv.c.trace_model.ProcessMemoryDump))
-throw new Error('Only supports process memory dumps');this.currentSelection_=selection;this.$.memory_dump_view.processMemoryDumps=[selection[0]];},get selection(){return this.currentSelection_;},get requiresTallView(){return true;}});'use strict';Polymer('tv-c-multi-process-memory-dump-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;selection=tv.b.asArray(selection).sort(tv.b.Range.compareByMinTimes);var table=this.$.content;table.tableColumns=[{title:'Dump',value:function(row){var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(row);});var spanEl=document.createElement('span');spanEl.textContent='Process memory dump at ';linkEl.appendChild(spanEl);linkEl.appendChild(tv.c.analysis.createTimeStamp(row.start));return linkEl;}}];table.showHeader=false;table.tableRows=selection;table.rebuild();}});'use strict';Polymer('tv-c-single-global-memory-dump-sub-view',{set selection(selection){if(selection.length!==1)
-throw new Error('Only supports a single global memory dump');if(!(selection[0]instanceof tv.c.trace_model.GlobalMemoryDump))
-throw new Error('Only supports global memory dumps');this.currentSelection_=selection;this.$.memory_dump_view.processMemoryDumps=tv.b.dictionaryValues(selection[0].processMemoryDumps);},get selection(){return this.currentSelection_;},get requiresTallView(){return true;}});'use strict';Polymer('tv-c-multi-global-memory-dump-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;selection=tv.b.asArray(selection).sort(tv.b.Range.compareByMinTimes);var table=this.$.content;table.tableColumns=[{title:'Dump',value:function(row){var linkEl=document.createElement('tv-c-analysis-link');linkEl.setSelectionAndContent(function(){return new tv.c.Selection(row);});var spanEl=document.createElement('span');spanEl.textContent='Global memory dump at ';linkEl.appendChild(spanEl);linkEl.appendChild(tv.c.analysis.createTimeStamp(row.start));return linkEl;}}];table.showHeader=false;table.tableRows=selection;table.rebuild();}});'use strict';(function(){var EventRegistry=tv.c.trace_model.EventRegistry;Polymer('tv-c-a-analysis-view',{ready:function(){this.tabView_=document.createElement('tracing-analysis-tab-view');this.tabView_.style.flex='1 1 auto';this.appendChild(this.tabView_);this.selectionController_=undefined;this.onSelectedTabChange_=this.onSelectedTabChange_.bind(this);this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.lastSeenSelection_=new tv.c.Selection();},set tallMode(value){if(value)
+return undefined;var selectedColumn=this.$.table.tableColumns[selectedColumnIndex];var selectedMemoryCell=selectedColumn.cell(selectedTableRow);return selectedMemoryCell;},updateContents_:function(){var processMemoryDumps=this.processMemoryDumps_||[];var rows=processMemoryDumps.map(function(processMemoryDump){function buildVMRegionsPane(){var pane=document.createElement('tr-c-a-memory-dump-vm-regions-details-pane');pane.vmRegions=processMemoryDump.mostRecentVmRegions;return pane;}
+var usedMemorySizes={};var totalResident=processMemoryDump.totalResidentBytes;if(totalResident!==undefined){var cell=new tr.c.analysis.MemoryCell(new tr.model.ScalarAttribute('bytes',totalResident));cell.buildDetailsPane=buildVMRegionsPane;usedMemorySizes['Total resident']=cell;}
+function addByteStatCell(byteStatName,columnTitle){var byteStat=processMemoryDump.getMostRecentTotalVmRegionStat(byteStatName);if(byteStat!==undefined){var cell=new tr.c.analysis.MemoryCell(new tr.model.ScalarAttribute('bytes',byteStat));cell.buildDetailsPane=buildVMRegionsPane;usedMemorySizes[columnTitle]=cell;}}
+addByteStatCell('proportionalResident','PSS');addByteStatCell('privateDirtyResident','Private dirty');addByteStatCell('swapped','Swapped');var allocatorSizes={};if(processMemoryDump.memoryAllocatorDumps!==undefined){processMemoryDump.memoryAllocatorDumps.forEach(function(dump){var attr=dump.attributes['size'];if(attr===undefined)
+attr=dump.attributes['outer_size'];var cell=new tr.c.analysis.MemoryCell(attr);cell.buildDetailsPane=function(){var pane=document.createElement('tr-c-a-memory-dump-allocator-details-pane');pane.memoryAllocatorDump=dump;return pane;};allocatorSizes[dump.fullName]=cell;},this);}
+return{title:processMemoryDump.process.userFriendlyName,usedMemorySizes:usedMemorySizes,allocatorSizes:allocatorSizes};},this);this.$.table.tableRows=rows;this.updateColumns_(rows);this.$.table.rebuild();},updateColumns_:function(rows){var titleColumn={title:'Process',value:function(row){var titleEl=document.createElement('tr-b-ui-color-legend');titleEl.label=row.title;return titleEl;},width:'200px',cmp:function(rowA,rowB){return rowA.title.localeCompare(rowB.title);},supportsCellSelection:false};var usedMemorySizeColumns=tr.c.analysis.MemoryColumn.fromRows(rows,'usedMemorySizes');var allocatorSizeColumns=tr.c.analysis.MemoryColumn.fromRows(rows,'allocatorSizes',function(allocatorName){var titleEl=document.createElement('tr-b-ui-color-legend');titleEl.label=allocatorName;return titleEl;});tr.c.analysis.MemoryColumn.sortByImportance(allocatorSizeColumns,IMPORTANCE_RULES);var tracingColumn=tr.b.findFirstInArray(allocatorSizeColumns,function(column){return column.name==='tracing';});if(tracingColumn!==undefined){var titleEl=document.createElement('span');titleEl.style.color='#999';titleEl.textContent='tracing';tracingColumn.title=titleEl;var oldValueCallback=tracingColumn.value;tracingColumn.value=function(row){var oldValue=oldValueCallback.call(this,row);if(!(oldValue instanceof HTMLElement))
+oldValue=document.createTextNode(oldValue);var valueEl=document.createElement('span');valueEl.style.color='#999';valueEl.appendChild(oldValue);return valueEl;};}
+var sizeColumns=usedMemorySizeColumns.concat(allocatorSizeColumns);tr.c.analysis.MemoryColumn.spaceEqually(sizeColumns);var columns=[titleColumn].concat(sizeColumns);this.$.table.tableColumns=columns;}});})();'use strict';Polymer('tr-c-a-memory-dump-view',{created:function(){this.processMemoryDumps_=undefined;},ready:function(){this.$.overview_pane.addEventListener('selected-memory-cell-changed',this.updateDetailsPane_.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.$.overview_pane.processMemoryDumps=this.processMemoryDumps_;this.updateDetailsPane_();},get processMemoryDumps(){return this.processMemoryDumps_;},updateDetailsPane_:function(){this.$.details_pane_container.textContent='';var selectedMemoryCell=this.$.overview_pane.selectedMemoryCell;if(!selectedMemoryCell||!selectedMemoryCell.buildDetailsPane)
+return;this.$.details_pane_container.appendChild(selectedMemoryCell.buildDetailsPane());}});'use strict';Polymer('tr-c-a-single-process-memory-dump-sub-view',{set selection(selection){if(selection.length!==1)
+throw new Error('Only supports a single process memory dump');if(!(selection[0]instanceof tr.model.ProcessMemoryDump))
+throw new Error('Only supports process memory dumps');this.currentSelection_=selection;this.$.memory_dump_view.processMemoryDumps=[selection[0]];},get selection(){return this.currentSelection_;},get requiresTallView(){return true;}});'use strict';Polymer('tr-c-a-multi-process-memory-dump-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;selection=tr.b.asArray(selection).sort(tr.b.Range.compareByMinTimes);var table=this.$.content;table.tableColumns=[{title:'Dump',value:function(row){var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(row);});var spanEl=document.createElement('span');spanEl.textContent='Process memory dump at ';linkEl.appendChild(spanEl);linkEl.appendChild(tr.b.units.createTimeStampSpan(row.start));return linkEl;}}];table.showHeader=false;table.tableRows=selection;table.rebuild();}});'use strict';Polymer('tr-c-a-single-global-memory-dump-sub-view',{set selection(selection){if(selection.length!==1)
+throw new Error('Only supports a single global memory dump');if(!(selection[0]instanceof tr.model.GlobalMemoryDump))
+throw new Error('Only supports global memory dumps');this.currentSelection_=selection;this.$.memory_dump_view.processMemoryDumps=tr.b.dictionaryValues(selection[0].processMemoryDumps);},get selection(){return this.currentSelection_;},get requiresTallView(){return true;}});'use strict';Polymer('tr-c-a-multi-global-memory-dump-sub-view',{created:function(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;selection=tr.b.asArray(selection).sort(tr.b.Range.compareByMinTimes);var table=this.$.content;table.tableColumns=[{title:'Dump',value:function(row){var linkEl=document.createElement('tr-c-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.c.Selection(row);});var spanEl=document.createElement('span');spanEl.textContent='Global memory dump at ';linkEl.appendChild(spanEl);linkEl.appendChild(tr.b.units.createTimeStampSpan(row.start));return linkEl;}}];table.showHeader=false;table.tableRows=selection;table.rebuild();}});'use strict';(function(){var EventRegistry=tr.model.EventRegistry;Polymer('tr-c-a-analysis-view',{ready:function(){this.tabView_=document.createElement('tracing-analysis-tab-view');this.tabView_.style.flex='1 1 auto';this.appendChild(this.tabView_);this.selectionController_=undefined;this.onSelectedTabChange_=this.onSelectedTabChange_.bind(this);this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.lastSeenSelection_=new tr.c.Selection();},set tallMode(value){if(value)
 this.classList.add('tall-mode');else
 this.classList.remove('tall-mode');},get tallMode(){return this.classList.contains('tall-mode');},get tabView(){return this.tabView_;},get selectionController(){return this.selectionController_;},set selectionController(selectionController){if(this.selectionController){this.selectionController_.removeEventListener('change',this.onSelectionChanged_);}
 this.selectionController_=selectionController;if(this.selectionController){this.selectionController_.addEventListener('change',this.onSelectionChanged_);}
 this.onSelectionChanged_();},get selection(){return this.selectionController_.selection;},onSelectionChanged_:function(e){var selection=this.selectionController_.selection;var selectionHasSameValue=this.lastSeenSelection_.equals(selection);this.lastSeenSelection_=selection;if(selectionHasSameValue)
 return;var lastSelectedTabTagName;var lastSelectedTabTypeName;if(this.tabView_.selectedTab){lastSelectedTabTagName=this.tabView_.selectedTab.tagName;lastSelectedTabTypeName=this.tabView_.selectedTab._eventTypeName;}
 this.tallMode=false;var previouslySelectedTab=this.tabView_.selectedTab;this.tabView_.removeEventListener('selected-tab-change',this.onSelectedTabChange_);this.tabView_.textContent='';if(selection.length==0){this.tabView_.tabStripHeadingText='Nothing selected. Tap stuff.';}else if(selection.length==1){this.tabView_.tabStripHeadingText='1 item selected: ';}else{this.tabView_.tabStripHeadingText=selection.length+' items selected: ';}
-var eventsByBaseTypeName=selection.getEventsOrganizedByBaseType(true);var numBaseTypesToAnalyze=tv.b.dictionaryLength(eventsByBaseTypeName);for(var eventTypeName in eventsByBaseTypeName){var subSelection=eventsByBaseTypeName[eventTypeName];var subView=this.createSubViewForSelection_(eventTypeName,subSelection);subView._eventTypeName=eventTypeName;this.tabView_.appendChild(subView);subView.selection=subSelection;}
+var eventsByBaseTypeName=selection.getEventsOrganizedByBaseType(true);var numBaseTypesToAnalyze=tr.b.dictionaryLength(eventsByBaseTypeName);for(var eventTypeName in eventsByBaseTypeName){var subSelection=eventsByBaseTypeName[eventTypeName];var subView=this.createSubViewForSelection_(eventTypeName,subSelection);subView._eventTypeName=eventTypeName;this.tabView_.appendChild(subView);subView.selection=subSelection;}
 var tab;if(lastSelectedTabTagName)
-tab=this.tabView_.querySelector(lastSelectedTabTagName);if(!tab&&lastSelectedTabTypeName){var tab=tv.b.findFirstInArray(this.tabView_.children,function(tab){return tab._eventTypeName===lastSelectedTabTypeName;});}
+tab=this.tabView_.querySelector(lastSelectedTabTagName);if(!tab&&lastSelectedTabTypeName){var tab=tr.b.findFirstInArray(this.tabView_.children,function(tab){return tab._eventTypeName===lastSelectedTabTypeName;});}
 if(!tab)
 tab=this.tabView_.firstChild;this.tabView_.selectedTab=tab;if(this.tabView_.selectedTab!==previouslySelectedTab)
 this.onSelectedTabChange_();this.tabView_.addEventListener('selected-tab-change',this.onSelectedTabChange_);},createSubViewForSelection_:function(eventTypeName,subSelection){var eventTypeInfo=EventRegistry.getEventTypeInfoByTypeName(eventTypeName);var singleMode=subSelection.length==1;var tagName;if(subSelection.length===1)
 tagName=eventTypeInfo.metadata.singleViewElementName;else
-tagName=eventTypeInfo.metadata.multiViewElementName;if(!tv.b.getPolymerElementNamed(tagName))
+tagName=eventTypeInfo.metadata.multiViewElementName;if(!tr.b.getPolymerElementNamed(tagName))
 throw new Error('Element not registered: '+tagName);var subView=document.createElement(tagName);var camelLabel;if(subSelection.length===1)
 camelLabel=EventRegistry.getUserFriendlySingularName(eventTypeName);else
 camelLabel=EventRegistry.getUserFriendlyPluralName(eventTypeName);subView.tabLabel=camelLabel+' ('+subSelection.length+')';return subView;},onSelectedTabChange_:function(){var selectionController=this.selectionController_;if(this.tabView_.selectedTab){var selectedTab=this.tabView_.selectedTab;this.tallMode=selectedTab.requiresTallView;if(selectionController){var rlth=selectedTab.relatedEventsToHighlight;selectionController.changeAnalysisViewRelatedEvents(rlth);}}else{this.tallMode=false;if(selectionController)
-selectionController.changeAnalysisViewRelatedEvents(undefined);}}});})();'use strict';tv.exportTo('tv.c',function(){var FaviconsByHue={blue:'data:image/vndmicrosofticon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjj8xAGArIgqOPzE8nUY3dqJJOJeiSTiXnUY3do4/MTxhKyIKjkAxAAAAAAAAAAAAAAAAAAAAAABQJBwAAAAAAZJBMzSoSzqlsU8+6bRQP/21UT//tVE//7RQP/2wTz3ppko6pY9AMjQAAAABTyMbAAAAAAB7e3sAAP//AKFSRE+wTz3dtVE//7VRP/+1UT//tVE//7VRP/+zUD7/sE89/7BOPf+qTDvdl0M0TwAAAABWJx4A+fn5ANjd3TnIiX7ftVA9/7VRP/+1UT//tVE//7VRP/+xTz3/rE08/6xMO/+sTDv/rE08/6dKOt+SQTM5q0w7ALO0tA3v8fGu05uR/7NMOf+0Tzz/tE88/7RPPv+uTT3/p0o7/6ZJOv+mSTr/pkk6/6ZJOv+mSjr/n0Y4rnIwKg3h4eFK9/j48N2zrP/FeGr/xnps/8Z6bP/AaUv/tlw1/7RbNf+1WzX/tFs1/7RbNf+0WzX/tFs1/7NbNPCqWy1K7e3tjPn5+f/49vX/9vLy//by8v/28vH/8bZv/+6RH//ukyP/7pMj/+6SI//ukiP/7pMj/+2SIv/qjyL/34kfjPHx8bL5+fn/+fn5//n5+f/5+fr/+fn5//W7cP/zlB3/85Yh//OWIf/zliH/85Yh//GVIf/rkR//6ZAf/+KLHrLz8/O2+fn5//n5+f/5+fn/+fn5//n5+f/1unD/85Qd//OWIf/zliH/85Yh//CUIP/mjh//44we/+OMHv/diR628vLymfn5+f/5+fn/+fn5//n5+f/5+fn/9bx0//OXI//zmCb/85gm/++VIv/hjB//3Yoe/92KHv/dih7/2IYdmfHx8Vz4+Pj3+fn5//n5+f/5+fn/+fn5//jo0//33bv/9929//bbtf/euDX/06oJ/9OrC//Tqwv/06oM98yfD1zr6+sY9/f3xvn5+f/5+fn/+fn5//n5+f/5+vv/+fv8//n7/f/3+PH/3Ms6/9O8AP/UvQD/1L0A/9K8AMbItAAY////APT09Fb4+Pjy+fn5//n5+f/5+fn/+fn5//n5+f/5+fr/9/bu/9zKOf/TuwD/1LwA/9S8APLQuABW3cQAAOzs7ADm5uYF9vb2ePn5+fT5+fn/+fn5//n5+f/5+fn/+fn6//f27v/cyTn/07sA/9S8APTRugB4w60ABcmyAAAAAAAA8PDwAOzs7Ab29vZd+Pj40vn5+fz5+fn/+fn5//n5+f/49/H/5Ndu/NjEIdLSugBdybIABsy1AAAAAAAAAAAAAAAAAADn5+cAqKioAPT09CH39/dy+Pj4tvj4+NX4+PjV+Pj4tvX063Lt6MMhOQAAAM+/RAAAAAAAAAAAAPAPAADAAwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCwUEDDgZExxWJx4tYiwiN2IsIjdWJx4tOBkTHAsFBAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAbDAkKZS0jMYs+MWydRjeipko6x6tMO9utTTzjrU0846tMO9umSjrHnUY3oos+MWxlLSMxGwwJCv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgZFAAPBwUHcjMoPJtFNpqsTTzhs1A+/LVRP/+2UT//tVE//7VRP/+1UT//tVE//7ZRP/+1UT//s1A+/KxNPOGbRTaacTInPA8HBQc4GRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/yp4AUCQcGZVDNICtTjzktVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+0UT//s1A+/7JQPv+rTDvkkkEzgE8jGxn/xZoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA////AGswJSqiSTivs1A++7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tFA+/7FPPf+xTz3/sU89/7FPPf+vTj37nkc3r2guJCr///8AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAP/DogB/VEwsqE09v7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7NQPv+vTj3/r049/69OPf+vTj3/r049/69OPf+uTjz/oUg4v20xJiz/nnsAAgEBAAAAAAAAAAAAAAAAAAAAAAD19fUAkp2fHdK2sbW5W0r/tVA+/7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+yUD7/rU08/6xNPP+tTTz/rU08/61NPP+tTTz/rU08/61NPP+sTTz/nkY3tWAqIR2pSzsAAAAAAAAAAAAAAAAAeXl5ADY2Ngnd39+O6tbT/blbSv+1UD7/tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//slA+/6xNPP+rTDv/q0w7/6tMO/+rTDv/q0w7/6tMO/+rTDv/q0w7/6tMO/+qTDv9lkM0jiUQDQlSJR0AAAAAAAAAAAD///8AxMTES/X29u3s2NX/uVtK/7VQPv+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7FPPv+qTDv/qEs6/6hLOv+oSzr/qEs6/6hLOv+oSzr/qEs6/6hLOv+oSzr/qEs6/6lLOv+lSTnthDsuS/+TcgAAAAAAm5ubAHBwcA/o6Oix+vv8/+zY1P+5W0r/tVA+/7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+xTz3/qEs6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+bRTaxSiEaD2cuJAD///8AycnJRfX19fD6+/z/69fU/7hYR/+0Tjv/tE48/7ROPP+0Tjz/tE48/7ROPP+0Tz3/r04+/6VJOv+jSDn/o0g5/6NIOf+jSDn/o0g5/6NIOf+jSDn/o0g5/6NIOf+jSDr/o0g5/6NIOf+jSDn/o0g6/6BHOfCCOS9F0FxKAAAAAALk5OSN+fn5//n6+v/y5+X/05uS/9CTiP/QlIn/0JSJ/9CUif/QlIn/0JSK/8yGb//AaDb/vWc0/71nNf+9ZzT/vWc0/71nNP+9ZjT/vWY0/71mNP+9ZjT/vGY0/7xmNP+8ZjT/vGY0/7xmNP+8ZjT/u2U0/7FiLY0AAAACk5OTFu/v78X5+fn/+fn5//n5+f/5+vr/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//KWI//ylSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//CUIf/vkyD/5Y0fxY1XExbDw8Mz9PT05fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LL/85cj//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/wlCD/7pIg/+6SIP/pjx/lunIZM9XV1VD39/f0+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fv9//fYsv/zlyP/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/75Mg/+uRH//qkB//6pAf/+iPH/TIfBtQ3d3dYfj4+Pn5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//OXI//zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh/+6TIP/ojx//548f/+ePH//njx//5o4f+c1/HGHh4eFl+Pj4+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LL/85cj//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/tkiD/5Y0f/+SNH//ljR//5Y0f/+WNH//kjB/6zn8cZeDg4Fr4+Pj3+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fv9//fYsv/zlyP/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/65Eg/+KMHv/iix7/4ose/+KLHv/iix7/4ose/+CLHvfLfRta3NzcQvf39+/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//OXI//zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh/+qRIP/gih7/34oe/9+KHv/fih7/34oe/9+KHv/fih7/3Yge78V6GkLS0tIj9fX12fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LH/85Yg//OVHv/zlR7/85Ue//OVHv/zlR7/85Ue//OVIf/pjyH/3ogf/92HH//dhx//3Ycf/92HH//dhx//3Ycf/92HH//ahh7ZunMZI56engjy8vKu+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fr7//jr2f/2ypL/9smP//bJkP/2yZD/9smQ//bJkP/2yZD/5rNI/9OeFP/SnhX/0p4V/9KeFf/SnhX/0Z0V/9GdFf/RnRX/0Z0V/8yWFq6KVBcI////AO3t7Wr5+fn++fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn6//n6/P/5+vz/+fr8//n6/P/5+vz/+fr8//n6/P/h013/0rsA/9O8AP/TvAD/07wA/9O8AP/TvAD/07wA/9O8AP/SvAD+yLMAav/mAADr6+sA4eHhJPb29tv5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+LSW//TuwD/1LwA/9S8AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9K6ANu/qgAkyLEAALu7uwAAAAAA8vLygfn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/4tJb/9O7AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9S8AP/UvAD/zrYAgQAAAACfjQAAAAAAAOzs7ADk5OQe9vb2zPn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i0lv/07sA/9S8AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9K6AMzCrAAeybIAAAAAAAAAAAAAsLCwAP///wDv7+9O+Pj47Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+LSW//TuwD/1LwA/9S8AP/UvAD/1LwA/9S8AP/TuwDsy7QATu7UAACXhQAAAAAAAAAAAAAAAAAA1tbWALS0tAPy8vJv+Pj49Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/4tJb/9O7AP/UvAD/1LwA/9S8AP/UvAD/07wA9M63AG6ZiQADtqIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4uLiANfX1wbz8/Nz+Pj48Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i0lv/07sA/9S8AP/UvAD/1LwA/9O8APDPuABzuKMABsGrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+PjANjY2ATy8vJZ+Pj42vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+HSW//TugD/1LsA/9S8AP/TuwDazrcAWbejAATBqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1NTUAB8fHwDw8PAr9vb2nPj4+O35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/7uas/+bZdv/j1mvt2cYznMu0ACsUFAAAtaEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr6wDj4+MG8vLyOvb29pD4+PjS+fn58vn5+f35+fn/+fn5//n5+f/5+fn/+fn5/fn5+fL4+frS9/j8kPT1/Trs8v8G8PP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh4eEA1tbWAu/v7xv09PRJ9vb2dvb29pf39/eo9/f3qPb29pf29vZ29PT0Se/v7xvW1tYC4eHhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA8AAAAPgAAAH4AAAB/AAAA/4AAAf/gAAf/8AAP//wAP/',green:'data:image/vndmicrosofticon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbWJLAEpCMwptYks8eWxTdn1wVpd9cFaXeWxTdm1iSzxKQzMKbWJLAAAAAAAAAAAAAAAAAAAAAAA+OCsAAAAAAXBlTTSBdFmliHpe6Yp8X/2LfWD/i31g/4p8X/2HeV3pf3NYpW5jTDQAAAABPTcqAAAAAAB7e3sAlv//AIB1Xk+HeV3di31g/4t9YP+LfWD/i31g/4t9YP+Je1//h3pd/4d5Xf+DdVrddGhQTwAAAABDPC4A+fn5ANrb3DmupZPfinxf/4t9YP+LfWD/i31g/4t9YP+Iel7/hHdb/4R2W/+Edlv/hHdb/4BzWN9wZU05g3ZaALS0tA3w8PGuu7Sj/4h5W/+Je17/iXte/4t8X/+HeFz/gnNY/4FyWP+Bclj/gXJY/4FyWP+Bclj/fG1Url9NPA3h4eFK9/j48MvFuf+kmoP/ppuF/6abhf+JkHL/c4Rj/3OEY/9zhGP/coNj/3KDY/9yg2P/coNj/3CDYvBgf19K7e3tjPn5+f/39vb/9fTz//X08//09PP/itKw/0m+h/9Mv4n/TL+J/0y/if9Mv4n/TL+J/0y+iP9Lu4b/RrJ/jPHx8bL5+fn/+fn5//n5+f/5+fn/+fn5/4rXtP9Hwon/SsOL/0rDi/9Kw4v/SsOL/0nCiv9HvYb/RruF/0S1gbLz8/O2+fn5//n5+f/5+fn/+fn5//n5+f+K17P/R8KJ/0rDi/9Kw4v/SsOL/0nBif9GuYT/RbaC/0W2gv9Dsn+28vLymfn5+f/5+fn/+fn5//n5+f/5+fn/jdi1/0vDjP9OxI7/TsSO/0rAiv9FtoP/RLKA/0SygP9EsoD/Qq59mfHx8Vz4+Pj3+fn5//n5+f/5+fn/+fn5/9rw5v/H6tn/yOra/8Lp2f9e1b7/O8yz/z3MtP89zLT/Pcuy9zzApVzr6+sY9/f3xvn5+f/5+fn/+fn5//n5+f/7+vr//Pr7//z6+//z+fn/ZuPY/zbczv853c7/Od3O/zjbzcY10sYY////APT09Fb4+Pjy+fn5//n5+f/5+fn/+fn5//n5+f/6+fn/8Pj3/2Xj1/823Mz/OdzN/znczfI42MlWO+XWAOzs7ADm5uYF9vb2ePn5+fT5+fn/+fn5//n5+f/5+fn/+vn5//D49/9j4tf/NdvM/znczfQ42ct4Ncu9BTbRwgAAAAAA8PDwAOzs7Ab29vZd+Pj40vn5+fz5+fn/+fn5//n5+f/z+Pj/jung/FLf0tI42ctdNdHCBjfUxgAAAAAAAAAAAAAAAADn5+cAqKioAPT09CH39/dy+Pj4tvj4+NX4+PjV+Pj4tu329XLO7+whAFQmAGrUygAAAAAAAAAAAPAPAADAAwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQgGDCsmHRxCOy4tS0M0N0tDNDdCOy4tKyYdHAkIBgwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAVEg4KTUU1MWtgSmx5bVOigHNYx4N2W9uFd1zjhXdc44N2W9uAc1jHeW1TomtgSmxNRjUxFRMOCv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsnHgALCggHWE88PHdrUpqEd1vhiXxf/It9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/iXxf/IR3W+F3a1KaV048PAsKCAcrJx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AAPjcqGXJnT4CFeFzki31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+KfWD/iXxf/4l7Xv+DdlrkcGVNgDw2Khn//+sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AFJKOSp9cFavinxf+4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/inxf/4h6Xv+Iel3/iHpd/4h6Xv+GeV37eW1Ur1BINyr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAP//3gBsZ1osgnVbv4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4l8X/+HeV3/hnlc/4Z5XP+GeVz/hnlc/4Z5XP+GeFz/fG9Vv1RLOiz/9LoAAgIBAAAAAAAAAAAAAAAAAAAAAAD19fUAl5ibHcbCurWShGn/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+Je1//hXhc/4R3W/+Fd1v/hXdb/4V3W/+Fd1v/hXdb/4V3W/+Ed1v/eW1TtUlCMh2CdVkAAAAAAAAAAAAAAAAAeXl5ADY2Ngne3t+O4t/Z/ZKFaf+LfV//i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/iXte/4R3W/+Ddlr/g3Za/4N2Wv+Ddlr/g3Za/4N2Wv+Ddlr/g3Za/4N2Wv+CdVr9c2dPjhwZEwk/OSsAAAAAAAAAAAD///8AxMTES/X19u3k4dv/koRp/4t9X/+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4h6Xv+CdVr/gXRZ/4F0Wf+BdFn/gXRZ/4F0Wf+BdFn/gXRZ/4F0Wf+BdFn/gXRZ/4F0Wf9+clftZVtGS/3jrgAAAAAAm5ubAHBwcA/o6Oix+/v7/+Pg2/+ShGn/i31f/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+Iel7/gXRZ/4BzWP+Ac1j/gHNY/4BzWP+Ac1j/gHNY/4BzWP+Ac1j/gHNY/4BzWP+Ac1j/gHNY/4BzWP93a1KxOTMnD1BHNwD///8AycnJRfX19fD7+/v/4+Da/5CCZ/+Jel3/iXtd/4l7Xf+Je13/iXtd/4l7Xf+Ke17/iHhd/4BxV/9/cFb/f3BW/39wVv9/cFb/f3BW/39wVv9/cFb/f3BW/39wVv9/cFb/f3BW/39wVv9/cFb/f3BW/31uVPBnWURFo45tAAAAAALk5OSN+fn5//r6+v/t7Oj/vLSk/7aunP+3rp3/t66d/7eunf+3rp3/uK+e/6Gmjv9vkG3/bI5r/2yOa/9sjmv/bI5r/2yOa/9sjmv/bI5r/2yOa/9sjmr/bI1q/2yNav9sjWr/bI1q/2uNav9rjWr/a41q/16GZI0AAAACk5OTFu/v78X5+fn/+fn5//n5+f/5+fr/+fn5//n5+f/5+fn/+fn5//n5+f/8+vv/wOfV/0vCi/9Kwor/SsKK/0rCiv9Kwor/SsKK/0rCiv9Kwor/SsKK/0rCiv9Kwor/SsKK/0rCiv9Kwor/SsKK/0nAif9Jv4j/RreCxStxUBbDw8Mz9PT05fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z6+/+/59X/TMSM/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9JwYn/SL6I/0i+iP9GuoXlOJVqM9XV1VD39/f0+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pr7/7/n1f9Mw4z/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/ScCJ/0e8hv9HvIb/R7yG/0a6hfQ9oXJQ3d3dYfj4+Pn5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8+vv/v+fV/0zDjP9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0i/iP9GuoX/RrqE/0a6hP9GuoT/RrmD+T6ldWHh4eFl+Pj4+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z6+/+/59X/TMOM/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Ivof/RbiD/0W3gv9FuIP/RbiD/0W4g/9Ft4L6PqZ2ZeDg4Fr4+Pj3+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pr7/7/n1f9Mw4z/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SL2H/0W2gv9FtYH/RbWB/0W1gf9FtYH/RbWB/0S0gPc+o3Ra3NzcQvf39+/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8+vv/v+fV/0zDjP9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0e8hv9EtID/RLOA/0SzgP9Es4D/RLOA/0SzgP9Es4D/Q7F/7zyecULS0tIj9fX12fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z6+/+/59X/SsOL/0jCiv9Iwor/SMKK/0jCiv9Iwor/SMKK/0rCiv9HuoT/RLF+/0Owff9EsH3/RLB9/0Swff9EsH3/RLB9/0Swff9CrnzZOJZrI56engjy8vKu+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vn6/9/x6f+l38X/o9/D/6Tfw/+k38P/pN/D/6Tfw/+k38T/a9Kz/0DBof9BwKH/QcCh/0HAof9BwKD/QcCg/0G/oP9Bv6D/Qb+g/0C4mK4tbU4I////AO3t7Wr5+fn++fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vn6//v6+//7+vv/+/r7//v6+//7+vv//Pr7//v6+/+B597/NdvN/znczf853M3/OdzN/znczf853M3/OdzN/znczf85283+NtHDakb/+gDr6+sA4eHhJPb29tv5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/3/n3f823Mz/OdzN/znczf853M3/OdzN/znczf853M3/OdzN/zjay9s0x7kkNs/BALu7uwAAAAAA8vLygfn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/f+fd/zbbzP853M3/OdzN/znczf853M3/OdzN/znczf853M3/N9XHgQAAAAAspZoAAAAAAOzs7ADk5OQe9vb2zPn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9/593/NtvM/znczf853M3/OdzN/znczf853M3/OdzN/zjay8w0yrweNtDCAAAAAAAAAAAAsLCwAP///wDv7+9O+Pj47Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/3/n3f8228z/OdzN/znczf853M3/OdzN/znczf8528zsN9PETkD45gAonJEAAAAAAAAAAAAAAAAA1tbWALS0tAPy8vJv+Pj49Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/f+fd/zbbzP853M3/OdzN/znczf853M3/OdvM9DjWx24qoJUDMb2wAAAAAAAAAAAAAAAAAAAAAAAAAAAA4uLiANfX1wbz8/Nz+Pj48Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9/593/NtvM/znczf853M3/OdzN/znbzPA418hzMr6xBjTIugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+PjANjY2ATy8vJZ+Pj42vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/37m3f8z28z/N9zN/znczf8528zaONbIWTK/sgQ0yLsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1NTUAB8fHwDw8PAr9vb2nPj4+O35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/vfDr/5Tq4v+L6ODtYODUnDTTxSsAGBsAMrywAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr6wDj4+MG8vLyOvb29pD4+PjS+fn58vn5+f35+fn/+fn5//n5+f/5+fn/+fn5/fn5+fL6+PjS+vf3kPv09Tr/6u4G/+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh4eEA1tbWAu/v7xv09PRJ9vb2dvb29pf39/eo9/f3qPb29pf29vZ29PT0Se/v7xvW1tYC4eHhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA8AAAAPgAAAH4AAAB/AAAA/4AAAf/gAAf/8AAP//wAP/',red:'data:image/vndmicrosofticon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQxmbAC0RagpDGZs8ShysdkwdspdMHbKXShysdkMZmzwuEWoKQxmcAAAAAAAAAAAAAAAAAAAAAAAmDlgAAAAAAUQanzRPHrilUx/B6VQgxf1VIMb/VSDG/1Qgxf1TH8DpTh22pUMZnDQAAAABJQ5XAAAAAAB7ensA//8AAFUrr09SH8DdVSDG/1Ugxv9VIMb/VSDG/1Ugxv9UH8P/Ux/B/1IfwP9QHrrdRxqlTwAAAAAoD14A+fn5ANzf1zmMatPfVB7G/1Ugxv9VIMb/VSDG/1Ugxv9TH8L/UR68/1AevP9QHrz/UR68/04dt99EGaA5UB67ALS0sw3x8u+unYDd/1AZxP9THcX/Ux3F/1Qexf9THr//Tx23/08ctv9PHbb/Tx22/08dtv9PHbb/SxuurjkSfg3h4eFK+Pj38LWf5P97UtL/fVXS/31V0/9fOcz/SSfC/0knwP9JJ8D/SSfA/0knwP9JJ8D/SSfA/0gnv/A/KLNK7e3tjPn5+f/29fj/8vD3//Px9//y8Pf/fILz/zQ/8P83QvD/N0Lw/zdC8P83QvD/N0Lw/zdB7/82QOz/Mz3gjPHx8bL5+fn/+fn5//n6+f/5+vn/+fn5/36G9v8yQPT/NkP0/zZD9P82Q/T/NkP0/zVC8v80QOz/M0Dq/zI+47Lz8/O2+fn5//n5+f/5+fn/+fn5//n5+f99hvb/MkD0/zZD9P82Q/T/NkP0/zVC8f8zP+f/Mj7k/zI+5P8xPd628vLymfn5+f/5+fn/+fn5//n5+f/5+fn/gYn2/zdE9P87R/T/O0f0/zZF8P8yQOP/MT/e/zE/3v8xP97/Lz3ZmfHx8Vz4+Pj3+fn5//n5+f/5+fn/+fn5/9fZ+P/Bxfj/wsb4/7vD+P87j/X/Dnzx/xF98f8RffH/EXzw9xZv5Vzr6+sY9/f3xvn5+f/5+fn/+fn5//n5+f/7+/n//Pz5//38+f/x+Pn/OrD+/wCY//8Amf//AJn//wCZ/cYAlPMY////APT09Fb4+Pjy+fn5//n5+f/5+fn/+fn5//n5+f/6+fn/7vX5/zmu/v8Al///AJj//wCY/vIAlfpWAJ//AOzs7ADm5uYF9vb2ePn5+fT5+fn/+fn5//n5+f/5+fn/+vn5/+71+f85rf7/AJb//wCY//QAlvx4AIzrBQCQ8gAAAAAA8PDwAOzs7Ab29vZd+Pj40vn5+fz5+fn/+fn5//n5+f/x9vn/bsP8/CGk/tIAlvxdAJDyBgCT9QAAAAAAAAAAAAAAAADn5+cAqKioAPT09CH39/dy+Pj4tvj4+NX4+PjV+Pj4tuvy93LD4fUhAAC7AESo6wAAAAAAAAAAAPAPAADAAwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgIMDBoKPRwoD14tLhFrNy4RazcoD14tGgo9HAYCDAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+3/wANBR0KLxJuMUEYmGxKHKyiTh22x1Aeu9tRHr3jUR6941Aeu9tOHbbHShysokEYmGwvEm4xDQUeCv+6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoKPgAHAxAHNhR9PEkbqppRHr3hVCDE/FUgxv9VIMf/VSDH/1Ugxv9VIMb/VSDH/1Ugx/9VIMb/VCDE/FEevOFIG6maNRR8PAcDEAcaCj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVUP8AJg5YGUYao4BRH77kVSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMX/VB/E/1Qfw/9QHrvkRRmggCUOVhnQTv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA////ADITdSpMHbKvVCDE+1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VCDE/1Mfwv9TH8H/Ux/B/1Mfwv9SH7/7ShytrzEScSr///8AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAMto/wBVPoYsUSC3v1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1QfxP9SHsD/Uh6//1Iev/9SHr//Uh6//1Iev/9SHr//SxywvzMTdyymPf8AAQACAAAAAAAAAAAAAAAAAAAAAAD19fUAnaKQHbep1rVfLcn/VB/G/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9UH8P/UR6+/1Eevf9RHr3/UR69/1Eevf9RHr3/UR69/1Eevf9RHr3/ShuttS0RaB1PHrkAAAAAAAAAAAAAAAAAeXl5ADY2Ngnf4NyO18zu/V8tyf9UH8b/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VB/D/1EevP9QHrr/UB67/1Aeu/9QHrv/UB67/1Aeu/9QHrv/UB67/1Aeu/9QHrr9RhqkjhEGKAknDloAAAAAAAAAAAD///8AxMTES/b39O3Zzu//Xy3J/1Qfxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Mfwv9QHbr/Tx24/08duP9PHbj/Tx24/08duP9PHbj/Tx24/08duP9PHbj/Tx24/08duf9NHLTtPheRS5s5/wAAAAAAm5ubAHBwcA/o6Oix+/z6/9jO7/9fLcn/VB/G/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9TH8H/Tx24/04dtv9OHbb/Th22/04dtv9OHbb/Th22/04dtv9OHbb/Th22/04dtv9OHbb/Th22/04dtv9JG6mxIw1RDzAScQD///8AycnJRfX19fD7/Pr/2M3v/1wqyP9SHMX/UhzF/1Icxf9SHMX/UhzF/1Icxf9THcX/Ux7A/04ctf9NHLL/Thyz/04cs/9NHLP/TRyz/00cs/9OHLP/Thyz/04cs/9OHLP/Thyz/04cs/9NHLP/Thyz/0wcsPA/Fo9FYyTkAAAAAALk5OSN+fn5//r6+f/n4vT/noDd/5Z22v+Wdtr/lnba/5Z22v+Wdtr/mHfb/35g1/9KMMr/SC/H/0gvx/9IL8f/SC/H/0gvx/9IL8b/SC/G/0gvxv9HL8b/Ry/G/0cvxv9HL8b/Ry/G/0cvxv9HL8X/Ry7F/z8tuI0AAAACk5OTFu/v78X5+fn/+fn5//n5+f/6+vn/+fr5//n6+f/5+vn/+fr5//n6+f/9/fn/ub73/zhF8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zVC8f81QvD/Mz/mxR8njhbDw8Mz9PT05fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z8+f+5vff/OEX0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P81QvH/NEHv/zRB7/8zQOrlKTO6M9XV1VD39/f0+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pz5/7m99/84RfT/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NULw/zRA7P80QOv/NEDr/zNA6fQsN8lQ3d3dYfj4+Pn5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8/Pn/ub33/zhF9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zVB7/8zQOn/Mz/o/zM/6P8zQOj/Mz/n+S04zmHh4eFl+Pj4+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z8+f+5vff/OEX0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P80Qe7/Mz/m/zM/5f8zP+b/Mz/m/zM/5v8yP+X6LjnPZeDg4Fr4+Pj3+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pz5/7m99/84RfT/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NEHs/zI+4/8yPuP/Mj7j/zI+4/8yPuP/Mj7j/zI+4fctOMxa3NzcQvf39+/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8/Pn/ub33/zhF9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zRA6/8xPeH/MT3g/zE94P8xPeD/MT3g/zE94P8xPeD/MT3e7ys2xkLS0tIj9fX12fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z8+f+4vff/NkP0/zNB9P80QfT/NEH0/zRB9P80QfT/NEH0/zZC8/81P+n/Mjze/zI73f8yO93/Mjvd/zI73f8yO93/Mjvd/zI73f8xO9rZKTO7I56engjy8vKu+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+/r5/9ze+P+covf/mqD3/5qg9/+aoPf/mqD3/5qg9/+aoPf/UoLz/x1p5/8eaeb/Hmnm/x5p5v8eaeX/Hmnl/x5p5f8eaOX/Hmjl/yBh3a4jJokI////AO3t7Wr5+fn++fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vr5//z8+f/8/Pn//Pz5//z8+f/8/Pn//Pz5//z8+f9dvfz/AJf+/wCZ/v8Amf7/AJn+/wCZ/v8Amf7/AJn+/wCZ/v8AmP7+AJLxagC4/wDr6+sA4eHhJPb29tv5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/1u8/f8Alv//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCW/NsAieckAI/xALu7uwAAAAAA8vLygfn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/W7z9/wCW//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJP3gQAAAAAAcr8AAAAAAOzs7ADk5OQe9vb2zPn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9bvP3/AJb//wCY//8AmP//AJj//wCY//8AmP//AJj//wCW/MwAi+oeAJDxAAAAAAAAAAAAsLCwAP///wDv7+9O+Pj47Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/1u8/f8Alv//AJj//wCY//8AmP//AJj//wCY//8Al/7sAJL0TgCr/wAAa7QAAAAAAAAAAAAAAAAA1tbWALS0tAPy8vJv+Pj49Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/W7z9/wCW//8AmP//AJj//wCY//8AmP//AJj+9ACU+G4AbrgDAIPaAAAAAAAAAAAAAAAAAAAAAAAAAAAA4uLiANfX1wbz8/Nz+Pj48Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9bvP3/AJb//wCY//8AmP//AJj//wCY/vAAlflzAITcBgCK5wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+PjANjY2ATy8vJZ+Pj42vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/1u7/f8Alf//AJf//wCY//8Al/7aAJT4WQCE3AQAiucAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1NTUAB8fHwDw8PAr9vb2nPj4+O35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/rNv7/3bG/P9rwfztM6r7nACR9SsAER0AAIPZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr6wDj4+MG8vLyOvb29pD4+PjS+fn58vn5+f35+fn/+fn5//n5+f/5+fn/+fn5/fn5+fL6+fjS/Pj2kP338jr/+eIG//fqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh4eEA1tbWAu/v7xv09PRJ9vb2dvb29pf39/eo9/f3qPb29pf29vZ29PT0Se/v7xvW1tYC4eHhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA8AAAAPgAAAH4AAAB/AAAA/4AAAf/gAAf/8AAP//wAP/',yellow:'data:image/vndmicrosofticon;base64,AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAZKhQAOWAiAEV0KgBFdCoAOWAiABkqFAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ZAAAChAHAEp8JwBvu10AgNeSAInluACN7c4Aj/DXAI/w1wCN7c4AieW4AIDXkgBvu10ASnwnAAoQBwA8ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbLgAAAAAFAFmWMwB/1YwAj/DXAJX7+QCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJX7+QCP79cAftWMAFmVMwAAAAUAGy4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7v8AAD1mFQB6zXYAkPLdAJf+/gCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP7/AJf+/wCV/P4AjvDdAHjKdgA8ZBUA6f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AABWkCYAh+KoAJb8+QCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJf+/wCV+v8AlPr/AJT6/wCV+v8Akvf5AIPdqABTjCYA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICABb//wAka5wqAozquwCY/v8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCX/f8Ak/j/AJP3/wCT9/8Ak/f/AJP3/wCT9/8Akvb/AIbiuwBZlyoA//8AAAECAAAAAAAAAAAAAAAAAAAAAADz8/MAqJaJHZDD5rQLnP7/AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8Alvz/AJL2/wCR9P8AkfT/AJH0/wCR9P8AkfT/AJH0/wCR9P8AkfT/AITftABQhh0AjO0AAAAAAAAAAAAAAAAAfX19ADw8PAni3tuPuuD5/Quc//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJb8/wCQ8/8Aj/H/AI/x/wCP8f8Aj/H/AI/x/wCP8f8Aj/H/AI/x/wCP8f8AjvD9AH7UjwAiOQkASHkAAAAAAAgICAD///8AxcXFT/j19O+94vv/Cpz//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCV+/8Aj/H/AI3u/wCN7v8Aje7/AI3u/wCN7v8Aje7/AI3u/wCN7v8Aje7/AI3u/wCO7v8AiunvAHC8TwD//wAABQgAqKioAHp6ehHp6em3/fv5/7zh+v8KnP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8Alfr/AI7u/wCM6/8AjOv/AIzr/wCM6/8AjOv/AIzr/wCM6/8AjOv/AIzr/wCM6/8AjOv/AIzr/wCM6/8Ag9y3AERyEQBenQD///8AzMzMTfb29vP9+/n/vOH6/wqb//8Alv//AJb//wCW//8Alv//AJb//wCW//8Al///AJT5/wCL6/8Aiej/AIno/wCJ6P8Aiej/AIno/wCJ6P8Aiej/AIno/wCJ6P8Aiej/AIno/wCJ6P8Aiej/AIno/wCH5fMAb75NAMP/AAAAAAXl5eWX+fn5//v6+f/T6vr/Wbv9/0+3/f9Qt/3/ULf9/1C3/f9Qt/3/Ubj9/zew+/8InO//B5nr/weZ6/8Hmev/B5nq/weZ6v8Hmer/B5nq/weZ6v8Hmer/B5jq/weY6v8HmOn/B5jp/weY6f8HmOn/Bpjp/weP15cBAAAFpKSkHfDw8M/5+fn/+fn5//n5+f/1+Pn/9Pf5//T3+f/09/n/9Pf5//T3+f/4+Pn/o+T6/wq//f8Hv/3/CL/9/wi//f8Iv/3/CL/9/wi//f8Iv/3/CL/8/wi+/P8Ivvz/CL78/wi+/P8Ivvz/CL78/we9+/8HvPr/BrbxzwR9pR3Ly8tA9fX17Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//36+f+l5vv/CcL//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hv/3/Br36/wa9+v8GuvbsBZnLQNra2mD39/f4+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//fr5/6Xm+/8Jwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B778/wa79/8Guvf/Brr3/wa59fgFo9hg4uLidPj4+P35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/9+vn/peb7/wnB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//we++/8GufX/Brj0/wa49P8GuPT/Brfz/QWm3XTk5OR6+Pj4/fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//36+f+l5vv/CcH//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hvfr/Brfy/wa28f8GtvH/Brbx/wa28f8GtfD9BafdeuXl5W/4+Pj8+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//fr5/6Xm+/8Jwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B7z5/wa17/8GtO7/BrTu/wa07v8GtO7/BrTu/waz7fwFpdtv4eHhVvj4+Pb5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/9+vn/peb7/wnB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//we7+P8Gsu3/BrHr/wax6/8Gsev/BrHr/wax6/8Gsev/BrDq9gWh1Vba2toz9vb25vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//36+f+k5fv/BsH//wPA//8DwP//A8D//wPA//8DwP//A8D//wXA//8Guvb/BrDq/wau6P8Gruj/Bq7o/wau6P8Gruj/Bq7o/wau6P8GreXmBZnLM7+/vxH09PTC+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+/r5/83v+v9x2vz/btn9/2/Z/f9v2f3/b9n9/2/Z/f9v2f3/RdL5/yXG7v8mxOz/JsTs/ybE6/8mxOv/JsTr/yXE6/8lw+v/JcPr/yK95cIQirAR////APDw8IH5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vn5//r5+f/6+fn/+vn5//r5+f/6+fn/+vn5//r5+f+H8Pz/Oer+/zzq/v886v7/POr+/zzq/v886v7/POr+/zzq/v886v3/OuDzgWz//wD09PQA5+fnNPf39+n5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/4Xw/f846///O+v//zvr//876///O+v//zvr//876///O+v//zvp/ek32+00Ouf6AMrKygCzs7MF8/Pzmvn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/hfD9/zjr//876///O+v//zvr//876///O+v//zvr//876///OuX5miqptwUwv88AAAAAAPPz8wDp6eku9/f33fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f+F8P3/OOv//zvr//876///O+v//zvr//876///O+v//zvp/d033O8uOuX5AAAAAAAAAAAAvr6+AP///wDx8fFl+Pj49fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/4Xw/f846///O+v//zvr//876///O+v//zvr//876v71OeP2ZY7//wAus8IAAAAAAAAAAAAAAAAA4ODgANPT0wj09PSI+fn5+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/hfD9/zjr//876///O+v//zvr//876///O+v/+jrm+Ygyx9gINdPlAAAAAAAAAAAAAAAAAAAAAAAAAAAA6enpAOHh4Q309PSM+fn5+Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f+F8P3/OOv//zvr//876///O+v//zvr//g65/qMNtXnDTjd7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6enpAOLi4gr09PRw+Pj45/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/4Pw/f816///Oev//zvr//876v7nOub5cDbW5wo33O4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ODgANHR0QLx8fE89/f3sfn5+fX5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/t/T7/4Xx/f+A8P31Xez8sTnk9zwuxdUCNtTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREAP///wDo6OgM9PT0Tff396T4+Pjf+fn5+Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+fj5+Pjf9vf3pPL09E3m6OgM7/3/APtbOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIwD19fUA4uLiBvHx8Sn19fVd9vb2jff396739/e99/f3vff396729vaN9fX1XfHx8Snl4uIG9PX1AFEnIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wD///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABgAAAAcAAAAPgAAAH4AAAB/AAAA/4AAAf/AAAP/8AAP//wAP/KAAAABAAAAAgAAAAAQAgAAAAAAAABAAAEgsAABILAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABorgAAS34IAHTDNQCC22wAh+OMAIfjjACC22wAdMQ1AEx/CABorwAAAAAAAAAAAAAAAAAAAAAAAEBrAAAAAAAAecswAIzsngCU+OUAl/37AJj+/wCY/v8Al/37AJP35QCL6Z4Ad8gwAAAAAAA+aQAAAAAAcXd6AP8AAAAOiNtNAJP32gCY//8AmP//AJj//wCY//8AmP//AJb8/wCU+f8Ak/j/AI7w2gB+1E0AAAAAAEd4APn7/ADc2NU5T7P33gCX//8AmP//AJj//wCY//8AmP//AJX6/wCR8/8AkPL/AJDz/wCQ8/8AjOzeAHrOOQCR9AC3t7cO8e/vsGnA/f8Alf//AJf//wCX//8Al///AJP4/wCN7v8AjOz/AIzs/wCM7P8AjOz/AIzt/wCG4rAAY6oO4uLiT/j39/GIzfz/Mav+/zSs/v80rP7/FaH5/wOV7f8DlOv/A5Tr/wOU6/8DlOv/A5Tr/wOU6/8Dk+jxBIvVT+3t7ZT5+fn/8fb5/+vz+f/r9Pn/6vP5/1nR+/8EvPz/B738/we9/P8Hvfz/B738/we9/P8HvPv/B7r4/wax7ZTy8vK7+fn5//n5+f/6+fn/+vn5//n5+f9e1f3/A8D//wfB//8Hwf//B8H//wfB//8HwP3/Brv3/wa59f8GtO678/Pzwfn5+f/5+fn/+fn5//n5+f/4+fn/XtX9/wPA//8Hwf//B8H//wfB//8Hv/z/Brfz/wa17/8Gte//BrHqwfPz86X5+fn/+fn5//n5+f/5+fn/+Pn5/2DW/f8Gwf//CsL//wrC//8Jv/v/CLXu/wix6f8Isen/CLHp/wet5KXy8vJo+fn5+vn5+f/5+fn/+fn5//n5+f/I7vr/quf7/6zn+/+m5/v/Tdz5/yzV9P8u1fT/LtX0/y7U8/ooyOpo7OzsH/f399D5+fn/+fn5//n5+f/5+fn//Pr5//36+f/++vn/9fn5/2rv/v857P//POz//zzs//886/3QOuLzH////wD09PRh+fn59vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//H4+f9o7v7/OOv//zvr//876//2Ouf6YUH//wDu7u4A6enpB/b29oT5+fn3+fn5//n5+f/5+fn/+fn5//n5+f/x+Pn/Zu7+/zfr//876//3Ouj8hDfc7wc44PMAAAAAAPHx8QDu7u4I9vb2aPj4+Nn5+fn9+fn5//n5+f/5+fn/8/n5/4zx/P1S7P7ZO+n8aDfh9Ag55PcAAAAAAAAAAAAAAAAA6+vrAN/f3wH19fUo9/f3fvj4+MH4+Pje+Pj43vj4+MHq9vh+w/H2KADM5wFk4e8AAAAAAAAAAADwDwAA4AcAAMADAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAAgAEAAMADAADgBwAA'};return{FaviconsByHue:FaviconsByHue};});'use strict';tv.exportTo('tv.c',function(){var Task=tv.b.Task;function FindController(selectionController){this.selectionController_=selectionController;this.filterText_='';this.filterHits_=new tv.c.Selection();this.filterHitsDirty_=true;this.currentHitIndex_=-1;};FindController.prototype={__proto__:Object.prototype,get model(){return this.selectionController_.model;},get selectionController(){return this.selectionController_;},get filterText(){return this.filterText_;},set filterText(f){if(f==this.filterText_)
-return;this.filterText_=f;this.filterHitsDirty_=true;},getFilterPromise_:function(filterText){if(!this.selectionController_)
-return;var promise=Promise.resolve();var sc=this.selectionController_;var filter=new tv.c.TitleOrCategoryFilter(filterText);var filterHits=new tv.c.Selection();var filterTask=sc.addAllEventsMatchingFilterToSelectionAsTask(filter,filterHits);promise=Task.RunWhenIdle(filterTask);promise.then(function(){this.filterHitsDirty_=false;this.filterHits_=filterHits;sc.findTextChangedTo(filterHits);}.bind(this));return promise;},clearFindSelections_:function(){this.selectionController_.findTextCleared();},updateFilterHits:function(){var promise=Promise.resolve();if(!this.filterHitsDirty_)
-return promise;this.filterHits_=new tv.c.Selection();this.currentHitIndex_=-1;var stateFromString;try{stateFromString=this.selectionController_.uiStateFromString(this.filterText);}catch(e){var overlay=new tv.b.ui.Overlay();overlay.textContent=e.message;overlay.title='UI State Navigation Error';overlay.visible=true;return promise;}
-if(stateFromString!==undefined){this.selectionController_.navToPosition(stateFromString,true);}else{if(this.filterText.length===0)
-this.clearFindSelections_();else
-promise=this.getFilterPromise_(this.filterText);}
-return promise;},get filterHits(){return this.filterHits_;},get currentHitIndex(){return this.currentHitIndex_;},find_:function(dir){var firstHit=this.currentHitIndex_===-1;if(firstHit&&dir<0)
+selectionController.changeAnalysisViewRelatedEvents(undefined);}}});})();'use strict';tr.exportTo('tr.c',function(){var FaviconsByHue={blue:'data:image/vndmicrosofticon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjj8xAGArIgqOPzE8nUY3dqJJOJeiSTiXnUY3do4/MTxhKyIKjkAxAAAAAAAAAAAAAAAAAAAAAABQJBwAAAAAAZJBMzSoSzqlsU8+6bRQP/21UT//tVE//7RQP/2wTz3ppko6pY9AMjQAAAABTyMbAAAAAAB7e3sAAP//AKFSRE+wTz3dtVE//7VRP/+1UT//tVE//7VRP/+zUD7/sE89/7BOPf+qTDvdl0M0TwAAAABWJx4A+fn5ANjd3TnIiX7ftVA9/7VRP/+1UT//tVE//7VRP/+xTz3/rE08/6xMO/+sTDv/rE08/6dKOt+SQTM5q0w7ALO0tA3v8fGu05uR/7NMOf+0Tzz/tE88/7RPPv+uTT3/p0o7/6ZJOv+mSTr/pkk6/6ZJOv+mSjr/n0Y4rnIwKg3h4eFK9/j48N2zrP/FeGr/xnps/8Z6bP/AaUv/tlw1/7RbNf+1WzX/tFs1/7RbNf+0WzX/tFs1/7NbNPCqWy1K7e3tjPn5+f/49vX/9vLy//by8v/28vH/8bZv/+6RH//ukyP/7pMj/+6SI//ukiP/7pMj/+2SIv/qjyL/34kfjPHx8bL5+fn/+fn5//n5+f/5+fr/+fn5//W7cP/zlB3/85Yh//OWIf/zliH/85Yh//GVIf/rkR//6ZAf/+KLHrLz8/O2+fn5//n5+f/5+fn/+fn5//n5+f/1unD/85Qd//OWIf/zliH/85Yh//CUIP/mjh//44we/+OMHv/diR628vLymfn5+f/5+fn/+fn5//n5+f/5+fn/9bx0//OXI//zmCb/85gm/++VIv/hjB//3Yoe/92KHv/dih7/2IYdmfHx8Vz4+Pj3+fn5//n5+f/5+fn/+fn5//jo0//33bv/9929//bbtf/euDX/06oJ/9OrC//Tqwv/06oM98yfD1zr6+sY9/f3xvn5+f/5+fn/+fn5//n5+f/5+vv/+fv8//n7/f/3+PH/3Ms6/9O8AP/UvQD/1L0A/9K8AMbItAAY////APT09Fb4+Pjy+fn5//n5+f/5+fn/+fn5//n5+f/5+fr/9/bu/9zKOf/TuwD/1LwA/9S8APLQuABW3cQAAOzs7ADm5uYF9vb2ePn5+fT5+fn/+fn5//n5+f/5+fn/+fn6//f27v/cyTn/07sA/9S8APTRugB4w60ABcmyAAAAAAAA8PDwAOzs7Ab29vZd+Pj40vn5+fz5+fn/+fn5//n5+f/49/H/5Ndu/NjEIdLSugBdybIABsy1AAAAAAAAAAAAAAAAAADn5+cAqKioAPT09CH39/dy+Pj4tvj4+NX4+PjV+Pj4tvX063Lt6MMhOQAAAM+/RAAAAAAAAAAAAPAPAADAAwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCwUEDDgZExxWJx4tYiwiN2IsIjdWJx4tOBkTHAsFBAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAbDAkKZS0jMYs+MWydRjeipko6x6tMO9utTTzjrU0846tMO9umSjrHnUY3oos+MWxlLSMxGwwJCv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgZFAAPBwUHcjMoPJtFNpqsTTzhs1A+/LVRP/+2UT//tVE//7VRP/+1UT//tVE//7ZRP/+1UT//s1A+/KxNPOGbRTaacTInPA8HBQc4GRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/yp4AUCQcGZVDNICtTjzktVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+0UT//s1A+/7JQPv+rTDvkkkEzgE8jGxn/xZoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA////AGswJSqiSTivs1A++7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tFA+/7FPPf+xTz3/sU89/7FPPf+vTj37nkc3r2guJCr///8AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAP/DogB/VEwsqE09v7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7NQPv+vTj3/r049/69OPf+vTj3/r049/69OPf+uTjz/oUg4v20xJiz/nnsAAgEBAAAAAAAAAAAAAAAAAAAAAAD19fUAkp2fHdK2sbW5W0r/tVA+/7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+yUD7/rU08/6xNPP+tTTz/rU08/61NPP+tTTz/rU08/61NPP+sTTz/nkY3tWAqIR2pSzsAAAAAAAAAAAAAAAAAeXl5ADY2Ngnd39+O6tbT/blbSv+1UD7/tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//slA+/6xNPP+rTDv/q0w7/6tMO/+rTDv/q0w7/6tMO/+rTDv/q0w7/6tMO/+qTDv9lkM0jiUQDQlSJR0AAAAAAAAAAAD///8AxMTES/X29u3s2NX/uVtK/7VQPv+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7FPPv+qTDv/qEs6/6hLOv+oSzr/qEs6/6hLOv+oSzr/qEs6/6hLOv+oSzr/qEs6/6lLOv+lSTnthDsuS/+TcgAAAAAAm5ubAHBwcA/o6Oix+vv8/+zY1P+5W0r/tVA+/7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+xTz3/qEs6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+bRTaxSiEaD2cuJAD///8AycnJRfX19fD6+/z/69fU/7hYR/+0Tjv/tE48/7ROPP+0Tjz/tE48/7ROPP+0Tz3/r04+/6VJOv+jSDn/o0g5/6NIOf+jSDn/o0g5/6NIOf+jSDn/o0g5/6NIOf+jSDr/o0g5/6NIOf+jSDn/o0g6/6BHOfCCOS9F0FxKAAAAAALk5OSN+fn5//n6+v/y5+X/05uS/9CTiP/QlIn/0JSJ/9CUif/QlIn/0JSK/8yGb//AaDb/vWc0/71nNf+9ZzT/vWc0/71nNP+9ZjT/vWY0/71mNP+9ZjT/vGY0/7xmNP+8ZjT/vGY0/7xmNP+8ZjT/u2U0/7FiLY0AAAACk5OTFu/v78X5+fn/+fn5//n5+f/5+vr/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//KWI//ylSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//CUIf/vkyD/5Y0fxY1XExbDw8Mz9PT05fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LL/85cj//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/wlCD/7pIg/+6SIP/pjx/lunIZM9XV1VD39/f0+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fv9//fYsv/zlyP/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/75Mg/+uRH//qkB//6pAf/+iPH/TIfBtQ3d3dYfj4+Pn5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//OXI//zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh/+6TIP/ojx//548f/+ePH//njx//5o4f+c1/HGHh4eFl+Pj4+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LL/85cj//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/tkiD/5Y0f/+SNH//ljR//5Y0f/+WNH//kjB/6zn8cZeDg4Fr4+Pj3+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fv9//fYsv/zlyP/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/65Eg/+KMHv/iix7/4ose/+KLHv/iix7/4ose/+CLHvfLfRta3NzcQvf39+/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//OXI//zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh/+qRIP/gih7/34oe/9+KHv/fih7/34oe/9+KHv/fih7/3Yge78V6GkLS0tIj9fX12fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LH/85Yg//OVHv/zlR7/85Ue//OVHv/zlR7/85Ue//OVIf/pjyH/3ogf/92HH//dhx//3Ycf/92HH//dhx//3Ycf/92HH//ahh7ZunMZI56engjy8vKu+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fr7//jr2f/2ypL/9smP//bJkP/2yZD/9smQ//bJkP/2yZD/5rNI/9OeFP/SnhX/0p4V/9KeFf/SnhX/0Z0V/9GdFf/RnRX/0Z0V/8yWFq6KVBcI////AO3t7Wr5+fn++fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn6//n6/P/5+vz/+fr8//n6/P/5+vz/+fr8//n6/P/h013/0rsA/9O8AP/TvAD/07wA/9O8AP/TvAD/07wA/9O8AP/SvAD+yLMAav/mAADr6+sA4eHhJPb29tv5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+LSW//TuwD/1LwA/9S8AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9K6ANu/qgAkyLEAALu7uwAAAAAA8vLygfn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/4tJb/9O7AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9S8AP/UvAD/zrYAgQAAAACfjQAAAAAAAOzs7ADk5OQe9vb2zPn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i0lv/07sA/9S8AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9K6AMzCrAAeybIAAAAAAAAAAAAAsLCwAP///wDv7+9O+Pj47Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+LSW//TuwD/1LwA/9S8AP/UvAD/1LwA/9S8AP/TuwDsy7QATu7UAACXhQAAAAAAAAAAAAAAAAAA1tbWALS0tAPy8vJv+Pj49Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/4tJb/9O7AP/UvAD/1LwA/9S8AP/UvAD/07wA9M63AG6ZiQADtqIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4uLiANfX1wbz8/Nz+Pj48Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i0lv/07sA/9S8AP/UvAD/1LwA/9O8APDPuABzuKMABsGrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+PjANjY2ATy8vJZ+Pj42vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+HSW//TugD/1LsA/9S8AP/TuwDazrcAWbejAATBqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1NTUAB8fHwDw8PAr9vb2nPj4+O35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/7uas/+bZdv/j1mvt2cYznMu0ACsUFAAAtaEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr6wDj4+MG8vLyOvb29pD4+PjS+fn58vn5+f35+fn/+fn5//n5+f/5+fn/+fn5/fn5+fL4+frS9/j8kPT1/Trs8v8G8PP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh4eEA1tbWAu/v7xv09PRJ9vb2dvb29pf39/eo9/f3qPb29pf29vZ29PT0Se/v7xvW1tYC4eHhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA8AAAAPgAAAH4AAAB/AAAA/4AAAf/gAAf/8AAP//wAP/',green:'data:image/vndmicrosofticon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbWJLAEpCMwptYks8eWxTdn1wVpd9cFaXeWxTdm1iSzxKQzMKbWJLAAAAAAAAAAAAAAAAAAAAAAA+OCsAAAAAAXBlTTSBdFmliHpe6Yp8X/2LfWD/i31g/4p8X/2HeV3pf3NYpW5jTDQAAAABPTcqAAAAAAB7e3sAlv//AIB1Xk+HeV3di31g/4t9YP+LfWD/i31g/4t9YP+Je1//h3pd/4d5Xf+DdVrddGhQTwAAAABDPC4A+fn5ANrb3DmupZPfinxf/4t9YP+LfWD/i31g/4t9YP+Iel7/hHdb/4R2W/+Edlv/hHdb/4BzWN9wZU05g3ZaALS0tA3w8PGuu7Sj/4h5W/+Je17/iXte/4t8X/+HeFz/gnNY/4FyWP+Bclj/gXJY/4FyWP+Bclj/fG1Url9NPA3h4eFK9/j48MvFuf+kmoP/ppuF/6abhf+JkHL/c4Rj/3OEY/9zhGP/coNj/3KDY/9yg2P/coNj/3CDYvBgf19K7e3tjPn5+f/39vb/9fTz//X08//09PP/itKw/0m+h/9Mv4n/TL+J/0y/if9Mv4n/TL+J/0y+iP9Lu4b/RrJ/jPHx8bL5+fn/+fn5//n5+f/5+fn/+fn5/4rXtP9Hwon/SsOL/0rDi/9Kw4v/SsOL/0nCiv9HvYb/RruF/0S1gbLz8/O2+fn5//n5+f/5+fn/+fn5//n5+f+K17P/R8KJ/0rDi/9Kw4v/SsOL/0nBif9GuYT/RbaC/0W2gv9Dsn+28vLymfn5+f/5+fn/+fn5//n5+f/5+fn/jdi1/0vDjP9OxI7/TsSO/0rAiv9FtoP/RLKA/0SygP9EsoD/Qq59mfHx8Vz4+Pj3+fn5//n5+f/5+fn/+fn5/9rw5v/H6tn/yOra/8Lp2f9e1b7/O8yz/z3MtP89zLT/Pcuy9zzApVzr6+sY9/f3xvn5+f/5+fn/+fn5//n5+f/7+vr//Pr7//z6+//z+fn/ZuPY/zbczv853c7/Od3O/zjbzcY10sYY////APT09Fb4+Pjy+fn5//n5+f/5+fn/+fn5//n5+f/6+fn/8Pj3/2Xj1/823Mz/OdzN/znczfI42MlWO+XWAOzs7ADm5uYF9vb2ePn5+fT5+fn/+fn5//n5+f/5+fn/+vn5//D49/9j4tf/NdvM/znczfQ42ct4Ncu9BTbRwgAAAAAA8PDwAOzs7Ab29vZd+Pj40vn5+fz5+fn/+fn5//n5+f/z+Pj/jung/FLf0tI42ctdNdHCBjfUxgAAAAAAAAAAAAAAAADn5+cAqKioAPT09CH39/dy+Pj4tvj4+NX4+PjV+Pj4tu329XLO7+whAFQmAGrUygAAAAAAAAAAAPAPAADAAwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQgGDCsmHRxCOy4tS0M0N0tDNDdCOy4tKyYdHAkIBgwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAVEg4KTUU1MWtgSmx5bVOigHNYx4N2W9uFd1zjhXdc44N2W9uAc1jHeW1TomtgSmxNRjUxFRMOCv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsnHgALCggHWE88PHdrUpqEd1vhiXxf/It9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/iXxf/IR3W+F3a1KaV048PAsKCAcrJx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AAPjcqGXJnT4CFeFzki31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+KfWD/iXxf/4l7Xv+DdlrkcGVNgDw2Khn//+sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AFJKOSp9cFavinxf+4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/inxf/4h6Xv+Iel3/iHpd/4h6Xv+GeV37eW1Ur1BINyr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAP//3gBsZ1osgnVbv4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4l8X/+HeV3/hnlc/4Z5XP+GeVz/hnlc/4Z5XP+GeFz/fG9Vv1RLOiz/9LoAAgIBAAAAAAAAAAAAAAAAAAAAAAD19fUAl5ibHcbCurWShGn/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+Je1//hXhc/4R3W/+Fd1v/hXdb/4V3W/+Fd1v/hXdb/4V3W/+Ed1v/eW1TtUlCMh2CdVkAAAAAAAAAAAAAAAAAeXl5ADY2Ngne3t+O4t/Z/ZKFaf+LfV//i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/iXte/4R3W/+Ddlr/g3Za/4N2Wv+Ddlr/g3Za/4N2Wv+Ddlr/g3Za/4N2Wv+CdVr9c2dPjhwZEwk/OSsAAAAAAAAAAAD///8AxMTES/X19u3k4dv/koRp/4t9X/+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4h6Xv+CdVr/gXRZ/4F0Wf+BdFn/gXRZ/4F0Wf+BdFn/gXRZ/4F0Wf+BdFn/gXRZ/4F0Wf9+clftZVtGS/3jrgAAAAAAm5ubAHBwcA/o6Oix+/v7/+Pg2/+ShGn/i31f/4t9YP+LfWD/i31g/4t9YP+LfWD/i31g/4t9YP+Iel7/gXRZ/4BzWP+Ac1j/gHNY/4BzWP+Ac1j/gHNY/4BzWP+Ac1j/gHNY/4BzWP+Ac1j/gHNY/4BzWP93a1KxOTMnD1BHNwD///8AycnJRfX19fD7+/v/4+Da/5CCZ/+Jel3/iXtd/4l7Xf+Je13/iXtd/4l7Xf+Ke17/iHhd/4BxV/9/cFb/f3BW/39wVv9/cFb/f3BW/39wVv9/cFb/f3BW/39wVv9/cFb/f3BW/39wVv9/cFb/f3BW/31uVPBnWURFo45tAAAAAALk5OSN+fn5//r6+v/t7Oj/vLSk/7aunP+3rp3/t66d/7eunf+3rp3/uK+e/6Gmjv9vkG3/bI5r/2yOa/9sjmv/bI5r/2yOa/9sjmv/bI5r/2yOa/9sjmr/bI1q/2yNav9sjWr/bI1q/2uNav9rjWr/a41q/16GZI0AAAACk5OTFu/v78X5+fn/+fn5//n5+f/5+fr/+fn5//n5+f/5+fn/+fn5//n5+f/8+vv/wOfV/0vCi/9Kwor/SsKK/0rCiv9Kwor/SsKK/0rCiv9Kwor/SsKK/0rCiv9Kwor/SsKK/0rCiv9Kwor/SsKK/0nAif9Jv4j/RreCxStxUBbDw8Mz9PT05fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z6+/+/59X/TMSM/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9JwYn/SL6I/0i+iP9GuoXlOJVqM9XV1VD39/f0+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pr7/7/n1f9Mw4z/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/ScCJ/0e8hv9HvIb/R7yG/0a6hfQ9oXJQ3d3dYfj4+Pn5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8+vv/v+fV/0zDjP9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0i/iP9GuoX/RrqE/0a6hP9GuoT/RrmD+T6ldWHh4eFl+Pj4+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z6+/+/59X/TMOM/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Ivof/RbiD/0W3gv9FuIP/RbiD/0W4g/9Ft4L6PqZ2ZeDg4Fr4+Pj3+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pr7/7/n1f9Mw4z/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SL2H/0W2gv9FtYH/RbWB/0W1gf9FtYH/RbWB/0S0gPc+o3Ra3NzcQvf39+/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8+vv/v+fV/0zDjP9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0rDi/9Kw4v/SsOL/0e8hv9EtID/RLOA/0SzgP9Es4D/RLOA/0SzgP9Es4D/Q7F/7zyecULS0tIj9fX12fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z6+/+/59X/SsOL/0jCiv9Iwor/SMKK/0jCiv9Iwor/SMKK/0rCiv9HuoT/RLF+/0Owff9EsH3/RLB9/0Swff9EsH3/RLB9/0Swff9CrnzZOJZrI56engjy8vKu+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vn6/9/x6f+l38X/o9/D/6Tfw/+k38P/pN/D/6Tfw/+k38T/a9Kz/0DBof9BwKH/QcCh/0HAof9BwKD/QcCg/0G/oP9Bv6D/Qb+g/0C4mK4tbU4I////AO3t7Wr5+fn++fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vn6//v6+//7+vv/+/r7//v6+//7+vv//Pr7//v6+/+B597/NdvN/znczf853M3/OdzN/znczf853M3/OdzN/znczf85283+NtHDakb/+gDr6+sA4eHhJPb29tv5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/3/n3f823Mz/OdzN/znczf853M3/OdzN/znczf853M3/OdzN/zjay9s0x7kkNs/BALu7uwAAAAAA8vLygfn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/f+fd/zbbzP853M3/OdzN/znczf853M3/OdzN/znczf853M3/N9XHgQAAAAAspZoAAAAAAOzs7ADk5OQe9vb2zPn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9/593/NtvM/znczf853M3/OdzN/znczf853M3/OdzN/zjay8w0yrweNtDCAAAAAAAAAAAAsLCwAP///wDv7+9O+Pj47Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/3/n3f8228z/OdzN/znczf853M3/OdzN/znczf8528zsN9PETkD45gAonJEAAAAAAAAAAAAAAAAA1tbWALS0tAPy8vJv+Pj49Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/f+fd/zbbzP853M3/OdzN/znczf853M3/OdvM9DjWx24qoJUDMb2wAAAAAAAAAAAAAAAAAAAAAAAAAAAA4uLiANfX1wbz8/Nz+Pj48Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9/593/NtvM/znczf853M3/OdzN/znbzPA418hzMr6xBjTIugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+PjANjY2ATy8vJZ+Pj42vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/37m3f8z28z/N9zN/znczf8528zaONbIWTK/sgQ0yLsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1NTUAB8fHwDw8PAr9vb2nPj4+O35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/vfDr/5Tq4v+L6ODtYODUnDTTxSsAGBsAMrywAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr6wDj4+MG8vLyOvb29pD4+PjS+fn58vn5+f35+fn/+fn5//n5+f/5+fn/+fn5/fn5+fL6+PjS+vf3kPv09Tr/6u4G/+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh4eEA1tbWAu/v7xv09PRJ9vb2dvb29pf39/eo9/f3qPb29pf29vZ29PT0Se/v7xvW1tYC4eHhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA8AAAAPgAAAH4AAAB/AAAA/4AAAf/gAAf/8AAP//wAP/',red:'data:image/vndmicrosofticon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQxmbAC0RagpDGZs8ShysdkwdspdMHbKXShysdkMZmzwuEWoKQxmcAAAAAAAAAAAAAAAAAAAAAAAmDlgAAAAAAUQanzRPHrilUx/B6VQgxf1VIMb/VSDG/1Qgxf1TH8DpTh22pUMZnDQAAAABJQ5XAAAAAAB7ensA//8AAFUrr09SH8DdVSDG/1Ugxv9VIMb/VSDG/1Ugxv9UH8P/Ux/B/1IfwP9QHrrdRxqlTwAAAAAoD14A+fn5ANzf1zmMatPfVB7G/1Ugxv9VIMb/VSDG/1Ugxv9TH8L/UR68/1AevP9QHrz/UR68/04dt99EGaA5UB67ALS0sw3x8u+unYDd/1AZxP9THcX/Ux3F/1Qexf9THr//Tx23/08ctv9PHbb/Tx22/08dtv9PHbb/SxuurjkSfg3h4eFK+Pj38LWf5P97UtL/fVXS/31V0/9fOcz/SSfC/0knwP9JJ8D/SSfA/0knwP9JJ8D/SSfA/0gnv/A/KLNK7e3tjPn5+f/29fj/8vD3//Px9//y8Pf/fILz/zQ/8P83QvD/N0Lw/zdC8P83QvD/N0Lw/zdB7/82QOz/Mz3gjPHx8bL5+fn/+fn5//n6+f/5+vn/+fn5/36G9v8yQPT/NkP0/zZD9P82Q/T/NkP0/zVC8v80QOz/M0Dq/zI+47Lz8/O2+fn5//n5+f/5+fn/+fn5//n5+f99hvb/MkD0/zZD9P82Q/T/NkP0/zVC8f8zP+f/Mj7k/zI+5P8xPd628vLymfn5+f/5+fn/+fn5//n5+f/5+fn/gYn2/zdE9P87R/T/O0f0/zZF8P8yQOP/MT/e/zE/3v8xP97/Lz3ZmfHx8Vz4+Pj3+fn5//n5+f/5+fn/+fn5/9fZ+P/Bxfj/wsb4/7vD+P87j/X/Dnzx/xF98f8RffH/EXzw9xZv5Vzr6+sY9/f3xvn5+f/5+fn/+fn5//n5+f/7+/n//Pz5//38+f/x+Pn/OrD+/wCY//8Amf//AJn//wCZ/cYAlPMY////APT09Fb4+Pjy+fn5//n5+f/5+fn/+fn5//n5+f/6+fn/7vX5/zmu/v8Al///AJj//wCY/vIAlfpWAJ//AOzs7ADm5uYF9vb2ePn5+fT5+fn/+fn5//n5+f/5+fn/+vn5/+71+f85rf7/AJb//wCY//QAlvx4AIzrBQCQ8gAAAAAA8PDwAOzs7Ab29vZd+Pj40vn5+fz5+fn/+fn5//n5+f/x9vn/bsP8/CGk/tIAlvxdAJDyBgCT9QAAAAAAAAAAAAAAAADn5+cAqKioAPT09CH39/dy+Pj4tvj4+NX4+PjV+Pj4tuvy93LD4fUhAAC7AESo6wAAAAAAAAAAAPAPAADAAwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgIMDBoKPRwoD14tLhFrNy4RazcoD14tGgo9HAYCDAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+3/wANBR0KLxJuMUEYmGxKHKyiTh22x1Aeu9tRHr3jUR6941Aeu9tOHbbHShysokEYmGwvEm4xDQUeCv+6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoKPgAHAxAHNhR9PEkbqppRHr3hVCDE/FUgxv9VIMf/VSDH/1Ugxv9VIMb/VSDH/1Ugx/9VIMb/VCDE/FEevOFIG6maNRR8PAcDEAcaCj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVUP8AJg5YGUYao4BRH77kVSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMX/VB/E/1Qfw/9QHrvkRRmggCUOVhnQTv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA////ADITdSpMHbKvVCDE+1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VCDE/1Mfwv9TH8H/Ux/B/1Mfwv9SH7/7ShytrzEScSr///8AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAMto/wBVPoYsUSC3v1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1QfxP9SHsD/Uh6//1Iev/9SHr//Uh6//1Iev/9SHr//SxywvzMTdyymPf8AAQACAAAAAAAAAAAAAAAAAAAAAAD19fUAnaKQHbep1rVfLcn/VB/G/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9UH8P/UR6+/1Eevf9RHr3/UR69/1Eevf9RHr3/UR69/1Eevf9RHr3/ShuttS0RaB1PHrkAAAAAAAAAAAAAAAAAeXl5ADY2Ngnf4NyO18zu/V8tyf9UH8b/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VB/D/1EevP9QHrr/UB67/1Aeu/9QHrv/UB67/1Aeu/9QHrv/UB67/1Aeu/9QHrr9RhqkjhEGKAknDloAAAAAAAAAAAD///8AxMTES/b39O3Zzu//Xy3J/1Qfxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Mfwv9QHbr/Tx24/08duP9PHbj/Tx24/08duP9PHbj/Tx24/08duP9PHbj/Tx24/08duf9NHLTtPheRS5s5/wAAAAAAm5ubAHBwcA/o6Oix+/z6/9jO7/9fLcn/VB/G/1Ugxv9VIMb/VSDG/1Ugxv9VIMb/VSDG/1Ugxv9TH8H/Tx24/04dtv9OHbb/Th22/04dtv9OHbb/Th22/04dtv9OHbb/Th22/04dtv9OHbb/Th22/04dtv9JG6mxIw1RDzAScQD///8AycnJRfX19fD7/Pr/2M3v/1wqyP9SHMX/UhzF/1Icxf9SHMX/UhzF/1Icxf9THcX/Ux7A/04ctf9NHLL/Thyz/04cs/9NHLP/TRyz/00cs/9OHLP/Thyz/04cs/9OHLP/Thyz/04cs/9NHLP/Thyz/0wcsPA/Fo9FYyTkAAAAAALk5OSN+fn5//r6+f/n4vT/noDd/5Z22v+Wdtr/lnba/5Z22v+Wdtr/mHfb/35g1/9KMMr/SC/H/0gvx/9IL8f/SC/H/0gvx/9IL8b/SC/G/0gvxv9HL8b/Ry/G/0cvxv9HL8b/Ry/G/0cvxv9HL8X/Ry7F/z8tuI0AAAACk5OTFu/v78X5+fn/+fn5//n5+f/6+vn/+fr5//n6+f/5+vn/+fr5//n6+f/9/fn/ub73/zhF8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zZD8v82Q/L/NkPy/zVC8f81QvD/Mz/mxR8njhbDw8Mz9PT05fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z8+f+5vff/OEX0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P81QvH/NEHv/zRB7/8zQOrlKTO6M9XV1VD39/f0+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pz5/7m99/84RfT/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NULw/zRA7P80QOv/NEDr/zNA6fQsN8lQ3d3dYfj4+Pn5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8/Pn/ub33/zhF9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zVB7/8zQOn/Mz/o/zM/6P8zQOj/Mz/n+S04zmHh4eFl+Pj4+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z8+f+5vff/OEX0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P80Qe7/Mz/m/zM/5f8zP+b/Mz/m/zM/5v8yP+X6LjnPZeDg4Fr4+Pj3+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//Pz5/7m99/84RfT/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NEHs/zI+4/8yPuP/Mj7j/zI+4/8yPuP/Mj7j/zI+4fctOMxa3NzcQvf39+/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/8/Pn/ub33/zhF9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zZD9P82Q/T/NkP0/zRA6/8xPeH/MT3g/zE94P8xPeD/MT3g/zE94P8xPeD/MT3e7ys2xkLS0tIj9fX12fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//z8+f+4vff/NkP0/zNB9P80QfT/NEH0/zRB9P80QfT/NEH0/zZC8/81P+n/Mjze/zI73f8yO93/Mjvd/zI73f8yO93/Mjvd/zI73f8xO9rZKTO7I56engjy8vKu+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+/r5/9ze+P+covf/mqD3/5qg9/+aoPf/mqD3/5qg9/+aoPf/UoLz/x1p5/8eaeb/Hmnm/x5p5v8eaeX/Hmnl/x5p5f8eaOX/Hmjl/yBh3a4jJokI////AO3t7Wr5+fn++fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vr5//z8+f/8/Pn//Pz5//z8+f/8/Pn//Pz5//z8+f9dvfz/AJf+/wCZ/v8Amf7/AJn+/wCZ/v8Amf7/AJn+/wCZ/v8AmP7+AJLxagC4/wDr6+sA4eHhJPb29tv5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/1u8/f8Alv//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCW/NsAieckAI/xALu7uwAAAAAA8vLygfn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/W7z9/wCW//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJP3gQAAAAAAcr8AAAAAAOzs7ADk5OQe9vb2zPn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9bvP3/AJb//wCY//8AmP//AJj//wCY//8AmP//AJj//wCW/MwAi+oeAJDxAAAAAAAAAAAAsLCwAP///wDv7+9O+Pj47Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/1u8/f8Alv//AJj//wCY//8AmP//AJj//wCY//8Al/7sAJL0TgCr/wAAa7QAAAAAAAAAAAAAAAAA1tbWALS0tAPy8vJv+Pj49Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/W7z9/wCW//8AmP//AJj//wCY//8AmP//AJj+9ACU+G4AbrgDAIPaAAAAAAAAAAAAAAAAAAAAAAAAAAAA4uLiANfX1wbz8/Nz+Pj48Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f9bvP3/AJb//wCY//8AmP//AJj//wCY/vAAlflzAITcBgCK5wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+PjANjY2ATy8vJZ+Pj42vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/1u7/f8Alf//AJf//wCY//8Al/7aAJT4WQCE3AQAiucAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1NTUAB8fHwDw8PAr9vb2nPj4+O35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/rNv7/3bG/P9rwfztM6r7nACR9SsAER0AAIPZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr6wDj4+MG8vLyOvb29pD4+PjS+fn58vn5+f35+fn/+fn5//n5+f/5+fn/+fn5/fn5+fL6+fjS/Pj2kP338jr/+eIG//fqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh4eEA1tbWAu/v7xv09PRJ9vb2dvb29pf39/eo9/f3qPb29pf29vZ29PT0Se/v7xvW1tYC4eHhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA8AAAAPgAAAH4AAAB/AAAA/4AAAf/gAAf/8AAP//wAP/',yellow:'data:image/vndmicrosofticon;base64,AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAZKhQAOWAiAEV0KgBFdCoAOWAiABkqFAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ZAAAChAHAEp8JwBvu10AgNeSAInluACN7c4Aj/DXAI/w1wCN7c4AieW4AIDXkgBvu10ASnwnAAoQBwA8ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbLgAAAAAFAFmWMwB/1YwAj/DXAJX7+QCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJX7+QCP79cAftWMAFmVMwAAAAUAGy4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7v8AAD1mFQB6zXYAkPLdAJf+/gCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP7/AJf+/wCV/P4AjvDdAHjKdgA8ZBUA6f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AABWkCYAh+KoAJb8+QCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJf+/wCV+v8AlPr/AJT6/wCV+v8Akvf5AIPdqABTjCYA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICABb//wAka5wqAozquwCY/v8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCX/f8Ak/j/AJP3/wCT9/8Ak/f/AJP3/wCT9/8Akvb/AIbiuwBZlyoA//8AAAECAAAAAAAAAAAAAAAAAAAAAADz8/MAqJaJHZDD5rQLnP7/AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8Alvz/AJL2/wCR9P8AkfT/AJH0/wCR9P8AkfT/AJH0/wCR9P8AkfT/AITftABQhh0AjO0AAAAAAAAAAAAAAAAAfX19ADw8PAni3tuPuuD5/Quc//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJb8/wCQ8/8Aj/H/AI/x/wCP8f8Aj/H/AI/x/wCP8f8Aj/H/AI/x/wCP8f8AjvD9AH7UjwAiOQkASHkAAAAAAAgICAD///8AxcXFT/j19O+94vv/Cpz//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCV+/8Aj/H/AI3u/wCN7v8Aje7/AI3u/wCN7v8Aje7/AI3u/wCN7v8Aje7/AI3u/wCO7v8AiunvAHC8TwD//wAABQgAqKioAHp6ehHp6em3/fv5/7zh+v8KnP//AJj//wCY//8AmP//AJj//wCY//8AmP//AJj//wCY//8Alfr/AI7u/wCM6/8AjOv/AIzr/wCM6/8AjOv/AIzr/wCM6/8AjOv/AIzr/wCM6/8AjOv/AIzr/wCM6/8Ag9y3AERyEQBenQD///8AzMzMTfb29vP9+/n/vOH6/wqb//8Alv//AJb//wCW//8Alv//AJb//wCW//8Al///AJT5/wCL6/8Aiej/AIno/wCJ6P8Aiej/AIno/wCJ6P8Aiej/AIno/wCJ6P8Aiej/AIno/wCJ6P8Aiej/AIno/wCH5fMAb75NAMP/AAAAAAXl5eWX+fn5//v6+f/T6vr/Wbv9/0+3/f9Qt/3/ULf9/1C3/f9Qt/3/Ubj9/zew+/8InO//B5nr/weZ6/8Hmev/B5nq/weZ6v8Hmer/B5nq/weZ6v8Hmer/B5jq/weY6v8HmOn/B5jp/weY6f8HmOn/Bpjp/weP15cBAAAFpKSkHfDw8M/5+fn/+fn5//n5+f/1+Pn/9Pf5//T3+f/09/n/9Pf5//T3+f/4+Pn/o+T6/wq//f8Hv/3/CL/9/wi//f8Iv/3/CL/9/wi//f8Iv/3/CL/8/wi+/P8Ivvz/CL78/wi+/P8Ivvz/CL78/we9+/8HvPr/BrbxzwR9pR3Ly8tA9fX17Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//36+f+l5vv/CcL//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hv/3/Br36/wa9+v8GuvbsBZnLQNra2mD39/f4+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//fr5/6Xm+/8Jwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B778/wa79/8Guvf/Brr3/wa59fgFo9hg4uLidPj4+P35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/9+vn/peb7/wnB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//we++/8GufX/Brj0/wa49P8GuPT/Brfz/QWm3XTk5OR6+Pj4/fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//36+f+l5vv/CcH//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hvfr/Brfy/wa28f8GtvH/Brbx/wa28f8GtfD9BafdeuXl5W/4+Pj8+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn//fr5/6Xm+/8Jwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B7z5/wa17/8GtO7/BrTu/wa07v8GtO7/BrTu/waz7fwFpdtv4eHhVvj4+Pb5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/9+vn/peb7/wnB//8Hwf//B8H//wfB//8Hwf//B8H//wfB//8Hwf//B8H//we7+P8Gsu3/BrHr/wax6/8Gsev/BrHr/wax6/8Gsev/BrDq9gWh1Vba2toz9vb25vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//36+f+k5fv/BsH//wPA//8DwP//A8D//wPA//8DwP//A8D//wXA//8Guvb/BrDq/wau6P8Gruj/Bq7o/wau6P8Gruj/Bq7o/wau6P8GreXmBZnLM7+/vxH09PTC+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+/r5/83v+v9x2vz/btn9/2/Z/f9v2f3/b9n9/2/Z/f9v2f3/RdL5/yXG7v8mxOz/JsTs/ybE6/8mxOv/JsTr/yXE6/8lw+v/JcPr/yK95cIQirAR////APDw8IH5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vn5//r5+f/6+fn/+vn5//r5+f/6+fn/+vn5//r5+f+H8Pz/Oer+/zzq/v886v7/POr+/zzq/v886v7/POr+/zzq/v886v3/OuDzgWz//wD09PQA5+fnNPf39+n5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/4Xw/f846///O+v//zvr//876///O+v//zvr//876///O+v//zvp/ek32+00Ouf6AMrKygCzs7MF8/Pzmvn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/hfD9/zjr//876///O+v//zvr//876///O+v//zvr//876///OuX5miqptwUwv88AAAAAAPPz8wDp6eku9/f33fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f+F8P3/OOv//zvr//876///O+v//zvr//876///O+v//zvp/d033O8uOuX5AAAAAAAAAAAAvr6+AP///wDx8fFl+Pj49fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/4Xw/f846///O+v//zvr//876///O+v//zvr//876v71OeP2ZY7//wAus8IAAAAAAAAAAAAAAAAA4ODgANPT0wj09PSI+fn5+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/hfD9/zjr//876///O+v//zvr//876///O+v/+jrm+Ygyx9gINdPlAAAAAAAAAAAAAAAAAAAAAAAAAAAA6enpAOHh4Q309PSM+fn5+Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f+F8P3/OOv//zvr//876///O+v//zvr//g65/qMNtXnDTjd7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6enpAOLi4gr09PRw+Pj45/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/4Pw/f816///Oev//zvr//876v7nOub5cDbW5wo33O4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ODgANHR0QLx8fE89/f3sfn5+fX5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/t/T7/4Xx/f+A8P31Xez8sTnk9zwuxdUCNtTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREAP///wDo6OgM9PT0Tff396T4+Pjf+fn5+Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+fj5+Pjf9vf3pPL09E3m6OgM7/3/APtbOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIwD19fUA4uLiBvHx8Sn19fVd9vb2jff396739/e99/f3vff396729vaN9fX1XfHx8Snl4uIG9PX1AFEnIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wD///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABgAAAAcAAAAPgAAAH4AAAB/AAAA/4AAAf/AAAP/8AAP//wAP/KAAAABAAAAAgAAAAAQAgAAAAAAAABAAAEgsAABILAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABorgAAS34IAHTDNQCC22wAh+OMAIfjjACC22wAdMQ1AEx/CABorwAAAAAAAAAAAAAAAAAAAAAAAEBrAAAAAAAAecswAIzsngCU+OUAl/37AJj+/wCY/v8Al/37AJP35QCL6Z4Ad8gwAAAAAAA+aQAAAAAAcXd6AP8AAAAOiNtNAJP32gCY//8AmP//AJj//wCY//8AmP//AJb8/wCU+f8Ak/j/AI7w2gB+1E0AAAAAAEd4APn7/ADc2NU5T7P33gCX//8AmP//AJj//wCY//8AmP//AJX6/wCR8/8AkPL/AJDz/wCQ8/8AjOzeAHrOOQCR9AC3t7cO8e/vsGnA/f8Alf//AJf//wCX//8Al///AJP4/wCN7v8AjOz/AIzs/wCM7P8AjOz/AIzt/wCG4rAAY6oO4uLiT/j39/GIzfz/Mav+/zSs/v80rP7/FaH5/wOV7f8DlOv/A5Tr/wOU6/8DlOv/A5Tr/wOU6/8Dk+jxBIvVT+3t7ZT5+fn/8fb5/+vz+f/r9Pn/6vP5/1nR+/8EvPz/B738/we9/P8Hvfz/B738/we9/P8HvPv/B7r4/wax7ZTy8vK7+fn5//n5+f/6+fn/+vn5//n5+f9e1f3/A8D//wfB//8Hwf//B8H//wfB//8HwP3/Brv3/wa59f8GtO678/Pzwfn5+f/5+fn/+fn5//n5+f/4+fn/XtX9/wPA//8Hwf//B8H//wfB//8Hv/z/Brfz/wa17/8Gte//BrHqwfPz86X5+fn/+fn5//n5+f/5+fn/+Pn5/2DW/f8Gwf//CsL//wrC//8Jv/v/CLXu/wix6f8Isen/CLHp/wet5KXy8vJo+fn5+vn5+f/5+fn/+fn5//n5+f/I7vr/quf7/6zn+/+m5/v/Tdz5/yzV9P8u1fT/LtX0/y7U8/ooyOpo7OzsH/f399D5+fn/+fn5//n5+f/5+fn//Pr5//36+f/++vn/9fn5/2rv/v857P//POz//zzs//886/3QOuLzH////wD09PRh+fn59vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//H4+f9o7v7/OOv//zvr//876//2Ouf6YUH//wDu7u4A6enpB/b29oT5+fn3+fn5//n5+f/5+fn/+fn5//n5+f/x+Pn/Zu7+/zfr//876//3Ouj8hDfc7wc44PMAAAAAAPHx8QDu7u4I9vb2aPj4+Nn5+fn9+fn5//n5+f/5+fn/8/n5/4zx/P1S7P7ZO+n8aDfh9Ag55PcAAAAAAAAAAAAAAAAA6+vrAN/f3wH19fUo9/f3fvj4+MH4+Pje+Pj43vj4+MHq9vh+w/H2KADM5wFk4e8AAAAAAAAAAADwDwAA4AcAAMADAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAAgAEAAMADAADgBwAA'};return{FaviconsByHue:FaviconsByHue};});'use strict';tr.exportTo('tr.c',function(){var Task=tr.b.Task;function FindController(selectionController){this.selectionController_=selectionController;this.filterHits_=new tr.c.Selection();this.currentHitIndex_=-1;this.activePromise_=Promise.resolve();this.activeTask_=undefined;};FindController.prototype={__proto__:Object.prototype,get model(){return this.selectionController_.model;},get selectionController(){return this.selectionController_;},enqueueOperation_:function(operation){var task;if(operation instanceof tr.b.Task)
+task=operation;else
+task=new tr.b.Task(operation,this);if(this.activeTask_){this.activeTask_=this.activeTask_.enqueue(task);}else{this.activeTask_=task;this.activePromise_=Task.RunWhenIdle(this.activeTask_);this.activePromise_.then(function(){this.activePromise_=undefined;this.activeTask_=undefined;}.bind(this));}},startFiltering:function(filterText){var sc=this.selectionController_;if(!sc)
+return;this.enqueueOperation_(function(){this.filterHits_=new tr.c.Selection();this.currentHitIndex_=-1;}.bind(this));var stateFromString;try{stateFromString=sc.uiStateFromString(filterText);}catch(e){this.enqueueOperation_(function(){var overlay=new tr.b.ui.Overlay();overlay.textContent=e.message;overlay.title='UI State Navigation Error';overlay.visible=true;});return this.activePromise_;}
+if(stateFromString!==undefined){this.enqueueOperation_(sc.navToPosition.bind(this,stateFromString,true));}else{if(filterText.length===0){this.enqueueOperation_(sc.findTextCleared.bind(sc));}else{var filter=new tr.c.TitleOrCategoryFilter(filterText);var filterHits=new tr.c.Selection();this.enqueueOperation_(sc.addAllEventsMatchingFilterToSelectionAsTask(filter,filterHits));this.enqueueOperation_(function(){this.filterHits_=filterHits;sc.findTextChangedTo(filterHits);}.bind(this));}}
+return this.activePromise_;},get filterHits(){return this.filterHits_;},get currentHitIndex(){return this.currentHitIndex_;},find_:function(dir){var firstHit=this.currentHitIndex_===-1;if(firstHit&&dir<0)
 this.currentHitIndex_=0;var N=this.filterHits.length;this.currentHitIndex_=(this.currentHitIndex_+dir+N)%N;if(!this.selectionController_)
-return;this.selectionController_.findFocusChangedTo(this.filterHits.subSelection(this.currentHitIndex_,1));},findNext:function(){this.find_(1);},findPrevious:function(){this.find_(-1);},reset:function(){this.filterText_='';this.filterHitsDirty_=true;}};return{FindController:FindController};});'use strict';tv.exportTo('tv.b',function(){function KeyEventManager(opt_document){this.document_=opt_document||document;if(KeyEventManager.instance)
+return;this.selectionController_.findFocusChangedTo(this.filterHits.subSelection(this.currentHitIndex_,1));},findNext:function(){this.find_(1);},findPrevious:function(){this.find_(-1);}};return{FindController:FindController};});'use strict';tr.exportTo('tr.b',function(){function KeyEventManager(opt_document){this.document_=opt_document||document;if(KeyEventManager.instance)
 throw new Error('KeyEventManager is a singleton.');this.onEvent_=this.onEvent_.bind(this);this.document_.addEventListener('keydown',this.onEvent_);this.document_.addEventListener('keypress',this.onEvent_);this.document_.addEventListener('keyup',this.onEvent_);this.listeners_=[];}
-KeyEventManager.instance=undefined;document.head.addEventListener('tv-unittest-will-run',function(){if(KeyEventManager.instance){KeyEventManager.instance.destroy();KeyEventManager.instance=undefined;}
-KeyEventManager.instance=new KeyEventManager();});KeyEventManager.prototype={addListener:function(type,handler,thisArg){if(!thisArg.keyEventManagerGuid_){thisArg.keyEventManagerGuid_=tv.b.GUID.allocate();thisArg.keyEventManagerRefCount_=0;}
+KeyEventManager.instance=undefined;document.head.addEventListener('tr-unittest-will-run',function(){if(KeyEventManager.instance){KeyEventManager.instance.destroy();KeyEventManager.instance=undefined;}
+KeyEventManager.instance=new KeyEventManager();});KeyEventManager.prototype={addListener:function(type,handler,thisArg){if(!thisArg.keyEventManagerGuid_){thisArg.keyEventManagerGuid_=tr.b.GUID.allocate();thisArg.keyEventManagerRefCount_=0;}
 thisArg.classList.add('key-event-manager-target');thisArg.keyEventManagerRefCount_++;var guid=thisArg.keyEventManagerGuid_;this.listeners_.push({guid:guid,type:type,handler:handler});},onEvent_:function(event){var preventDefaultState=undefined;var stopPropagationCalled=false;var oldPreventDefault=event.preventDefault;event.preventDefault=function(){preventDefaultState=false;oldPreventDefault.call(this);};var oldStopPropagation=event.stopPropagation;event.stopPropagation=function(){stopPropagationCalled=true;oldStopPropagation.call(this);};event.stopImmediatePropagation=function(){throw new Error('Not implemented');};var possibleThisArgs=this.document_.querySelectorAll('.key-event-manager-target');var possibleThisArgsByGUID={};for(var i=0;i<possibleThisArgs.length;i++){possibleThisArgsByGUID[possibleThisArgs[i].keyEventManagerGuid_]=possibleThisArgs[i];}
 var listeners=this.listeners_.concat();var type=event.type;var prevented=0;for(var i=0;i<listeners.length;i++){var listener=listeners[i];if(listener.type!==type)
 continue;var thisArg=possibleThisArgsByGUID[listener.guid];if(!thisArg)
@@ -2969,20 +3040,20 @@
 throw new Error('Was not registered with KeyEventManager');if(thisArg.keyEventManagerRefCount_===0)
 throw new Error('No events were registered on the provided thisArg');for(var i=0;i<this.listeners_.length;i++){var listener=this.listeners_[i];if(listener.type==type&&listener.handler==handler&&listener.guid==thisArg.keyEventManagerGuid_){thisArg.keyEventManagerRefCount_--;if(thisArg.keyEventManagerRefCount_===0)
 thisArg.classList.remove('key-event-manager-target');this.listeners_.splice(i,1);return;}}
-throw new Error('Listener not found');},destroy:function(){this.listeners_.splice(0);this.document_.removeEventListener('keydown',this.onEvent_);this.document_.removeEventListener('keypress',this.onEvent_);this.document_.removeEventListener('keyup',this.onEvent_);},dispatchFakeEvent:function(type,args){var e=new KeyboardEvent(type,args);return KeyEventManager.instance.onEvent_.call(undefined,e);}};KeyEventManager.instance=new KeyEventManager();return{KeyEventManager:KeyEventManager};});'use strict';tv.exportTo('tv.b.ui',function(){function MouseTracker(opt_targetElement){this.onMouseDown_=this.onMouseDown_.bind(this);this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.targetElement=opt_targetElement;}
+throw new Error('Listener not found');},destroy:function(){this.listeners_.splice(0);this.document_.removeEventListener('keydown',this.onEvent_);this.document_.removeEventListener('keypress',this.onEvent_);this.document_.removeEventListener('keyup',this.onEvent_);},dispatchFakeEvent:function(type,args){var e=new KeyboardEvent(type,args);return KeyEventManager.instance.onEvent_.call(undefined,e);}};KeyEventManager.instance=new KeyEventManager();return{KeyEventManager:KeyEventManager};});'use strict';tr.exportTo('tr.b.ui',function(){function MouseTracker(opt_targetElement){this.onMouseDown_=this.onMouseDown_.bind(this);this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.targetElement=opt_targetElement;}
 MouseTracker.prototype={get targetElement(){return this.targetElement_;},set targetElement(targetElement){if(this.targetElement_)
 this.targetElement_.removeEventListener('mousedown',this.onMouseDown_);this.targetElement_=targetElement;if(this.targetElement_)
 this.targetElement_.addEventListener('mousedown',this.onMouseDown_);},onMouseDown_:function(e){if(e.button!==0)
-return true;e=this.remakeEvent_(e,'mouse-tracker-start');this.targetElement_.dispatchEvent(e);document.addEventListener('mousemove',this.onMouseMove_);document.addEventListener('mouseup',this.onMouseUp_);this.targetElement_.addEventListener('blur',this.onMouseUp_);this.savePreviousUserSelect_=document.body.style['-webkit-user-select'];document.body.style['-webkit-user-select']='none';e.preventDefault();return true;},onMouseMove_:function(e){e=this.remakeEvent_(e,'mouse-tracker-move');this.targetElement_.dispatchEvent(e);},onMouseUp_:function(e){document.removeEventListener('mousemove',this.onMouseMove_);document.removeEventListener('mouseup',this.onMouseUp_);this.targetElement_.removeEventListener('blur',this.onMouseUp_);document.body.style['-webkit-user-select']=this.savePreviousUserSelect_;e=this.remakeEvent_(e,'mouse-tracker-end');this.targetElement_.dispatchEvent(e);},remakeEvent_:function(e,newType){var remade=new tv.b.Event(newType,true,true);remade.x=e.x;remade.y=e.y;remade.offsetX=e.offsetX;remade.offsetY=e.offsetY;remade.clientX=e.clientX;remade.clientY=e.clientY;return remade;}};function trackMouseMovesUntilMouseUp(mouseMoveHandler,opt_mouseUpHandler){function cleanupAndDispatchToMouseUp(e){document.removeEventListener('mousemove',mouseMoveHandler);document.removeEventListener('mouseup',cleanupAndDispatchToMouseUp);if(opt_mouseUpHandler)
+return true;e=this.remakeEvent_(e,'mouse-tracker-start');this.targetElement_.dispatchEvent(e);document.addEventListener('mousemove',this.onMouseMove_);document.addEventListener('mouseup',this.onMouseUp_);this.targetElement_.addEventListener('blur',this.onMouseUp_);this.savePreviousUserSelect_=document.body.style['-webkit-user-select'];document.body.style['-webkit-user-select']='none';e.preventDefault();return true;},onMouseMove_:function(e){e=this.remakeEvent_(e,'mouse-tracker-move');this.targetElement_.dispatchEvent(e);},onMouseUp_:function(e){document.removeEventListener('mousemove',this.onMouseMove_);document.removeEventListener('mouseup',this.onMouseUp_);this.targetElement_.removeEventListener('blur',this.onMouseUp_);document.body.style['-webkit-user-select']=this.savePreviousUserSelect_;e=this.remakeEvent_(e,'mouse-tracker-end');this.targetElement_.dispatchEvent(e);},remakeEvent_:function(e,newType){var remade=new tr.b.Event(newType,true,true);remade.x=e.x;remade.y=e.y;remade.offsetX=e.offsetX;remade.offsetY=e.offsetY;remade.clientX=e.clientX;remade.clientY=e.clientY;return remade;}};function trackMouseMovesUntilMouseUp(mouseMoveHandler,opt_mouseUpHandler){function cleanupAndDispatchToMouseUp(e){document.removeEventListener('mousemove',mouseMoveHandler);document.removeEventListener('mouseup',cleanupAndDispatchToMouseUp);if(opt_mouseUpHandler)
 opt_mouseUpHandler(e);}
 document.addEventListener('mousemove',mouseMoveHandler);document.addEventListener('mouseup',cleanupAndDispatchToMouseUp);}
-return{MouseTracker:MouseTracker,trackMouseMovesUntilMouseUp:trackMouseMovesUntilMouseUp};});'use strict';tv.exportTo('tv.b.ui',function(){var THIS_DOC=document.currentScript.ownerDocument;var MIN_MOUSE_SELECTION_DISTANCE=4;var MOUSE_SELECTOR_MODE={};MOUSE_SELECTOR_MODE.SELECTION=0x1;MOUSE_SELECTOR_MODE.PANSCAN=0x2;MOUSE_SELECTOR_MODE.ZOOM=0x4;MOUSE_SELECTOR_MODE.TIMING=0x8;MOUSE_SELECTOR_MODE.ROTATE=0x10;MOUSE_SELECTOR_MODE.ALL_MODES=0x1F;var allModeInfo={};allModeInfo[MOUSE_SELECTOR_MODE.PANSCAN]={title:'pan',className:'pan-scan-mode-button',eventNames:{enter:'enterpan',begin:'beginpan',update:'updatepan',end:'endpan',exit:'exitpan'}};allModeInfo[MOUSE_SELECTOR_MODE.SELECTION]={title:'selection',className:'selection-mode-button',eventNames:{enter:'enterselection',begin:'beginselection',update:'updateselection',end:'endselection',exit:'exitselection'}};allModeInfo[MOUSE_SELECTOR_MODE.ZOOM]={title:'zoom',className:'zoom-mode-button',eventNames:{enter:'enterzoom',begin:'beginzoom',update:'updatezoom',end:'endzoom',exit:'exitzoom'}};allModeInfo[MOUSE_SELECTOR_MODE.TIMING]={title:'timing',className:'timing-mode-button',eventNames:{enter:'entertiming',begin:'begintiming',update:'updatetiming',end:'endtiming',exit:'exittiming'}};allModeInfo[MOUSE_SELECTOR_MODE.ROTATE]={title:'rotate',className:'rotate-mode-button',eventNames:{enter:'enterrotate',begin:'beginrotate',update:'updaterotate',end:'endrotate',exit:'exitrotate'}};var MODIFIER={SHIFT:0x1,SPACE:0x2,CMD_OR_CTRL:0x4};var MouseModeSelector=tv.b.ui.define('div');MouseModeSelector.prototype={__proto__:HTMLDivElement.prototype,decorate:function(opt_targetElement){this.classList.add('mouse-mode-selector');var node=tv.b.instantiateTemplate('#mouse-mode-selector-template',THIS_DOC);this.appendChild(node);this.buttonsEl_=this.querySelector('.buttons');this.dragHandleEl_=this.querySelector('.drag-handle');this.supportedModeMask=MOUSE_SELECTOR_MODE.ALL_MODES;this.initialRelativeMouseDownPos_={x:0,y:0};this.defaultMode_=MOUSE_SELECTOR_MODE.PANSCAN;this.settingsKey_=undefined;this.mousePos_={x:0,y:0};this.mouseDownPos_={x:0,y:0};this.dragHandleEl_.addEventListener('mousedown',this.onDragHandleMouseDown_.bind(this));this.onMouseDown_=this.onMouseDown_.bind(this);this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.buttonsEl_.addEventListener('mouseup',this.onButtonMouseUp_);this.buttonsEl_.addEventListener('mousedown',this.onButtonMouseDown_);this.buttonsEl_.addEventListener('click',this.onButtonPress_.bind(this));tv.b.KeyEventManager.instance.addListener('keydown',this.onKeyDown_,this);tv.b.KeyEventManager.instance.addListener('keyup',this.onKeyUp_,this);this.keyCodeCondition=undefined;this.mode_=undefined;this.modeToKeyCodeMap_={};this.modifierToModeMap_={};this.targetElement=opt_targetElement;this.spacePressed_=false;this.modeBeforeAlternativeModeActivated_=null;this.isInteracting_=false;this.isClick_=false;},get targetElement(){return this.targetElement_;},set targetElement(target){if(this.targetElement_)
+return{MouseTracker:MouseTracker,trackMouseMovesUntilMouseUp:trackMouseMovesUntilMouseUp};});'use strict';tr.exportTo('tr.b.ui',function(){var THIS_DOC=document.currentScript.ownerDocument;var MIN_MOUSE_SELECTION_DISTANCE=4;var MOUSE_SELECTOR_MODE={};MOUSE_SELECTOR_MODE.SELECTION=0x1;MOUSE_SELECTOR_MODE.PANSCAN=0x2;MOUSE_SELECTOR_MODE.ZOOM=0x4;MOUSE_SELECTOR_MODE.TIMING=0x8;MOUSE_SELECTOR_MODE.ROTATE=0x10;MOUSE_SELECTOR_MODE.ALL_MODES=0x1F;var allModeInfo={};allModeInfo[MOUSE_SELECTOR_MODE.PANSCAN]={title:'pan',className:'pan-scan-mode-button',eventNames:{enter:'enterpan',begin:'beginpan',update:'updatepan',end:'endpan',exit:'exitpan'}};allModeInfo[MOUSE_SELECTOR_MODE.SELECTION]={title:'selection',className:'selection-mode-button',eventNames:{enter:'enterselection',begin:'beginselection',update:'updateselection',end:'endselection',exit:'exitselection'}};allModeInfo[MOUSE_SELECTOR_MODE.ZOOM]={title:'zoom',className:'zoom-mode-button',eventNames:{enter:'enterzoom',begin:'beginzoom',update:'updatezoom',end:'endzoom',exit:'exitzoom'}};allModeInfo[MOUSE_SELECTOR_MODE.TIMING]={title:'timing',className:'timing-mode-button',eventNames:{enter:'entertiming',begin:'begintiming',update:'updatetiming',end:'endtiming',exit:'exittiming'}};allModeInfo[MOUSE_SELECTOR_MODE.ROTATE]={title:'rotate',className:'rotate-mode-button',eventNames:{enter:'enterrotate',begin:'beginrotate',update:'updaterotate',end:'endrotate',exit:'exitrotate'}};var MODIFIER={SHIFT:0x1,SPACE:0x2,CMD_OR_CTRL:0x4};var MouseModeSelector=tr.b.ui.define('div');MouseModeSelector.prototype={__proto__:HTMLDivElement.prototype,decorate:function(opt_targetElement){this.classList.add('mouse-mode-selector');var node=tr.b.instantiateTemplate('#mouse-mode-selector-template',THIS_DOC);this.appendChild(node);this.buttonsEl_=this.querySelector('.buttons');this.dragHandleEl_=this.querySelector('.drag-handle');this.supportedModeMask=MOUSE_SELECTOR_MODE.ALL_MODES;this.initialRelativeMouseDownPos_={x:0,y:0};this.defaultMode_=MOUSE_SELECTOR_MODE.PANSCAN;this.settingsKey_=undefined;this.mousePos_={x:0,y:0};this.mouseDownPos_={x:0,y:0};this.dragHandleEl_.addEventListener('mousedown',this.onDragHandleMouseDown_.bind(this));this.onMouseDown_=this.onMouseDown_.bind(this);this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.buttonsEl_.addEventListener('mouseup',this.onButtonMouseUp_);this.buttonsEl_.addEventListener('mousedown',this.onButtonMouseDown_);this.buttonsEl_.addEventListener('click',this.onButtonPress_.bind(this));tr.b.KeyEventManager.instance.addListener('keydown',this.onKeyDown_,this);tr.b.KeyEventManager.instance.addListener('keyup',this.onKeyUp_,this);this.keyCodeCondition=undefined;this.mode_=undefined;this.modeToKeyCodeMap_={};this.modifierToModeMap_={};this.targetElement=opt_targetElement;this.spacePressed_=false;this.modeBeforeAlternativeModeActivated_=null;this.isInteracting_=false;this.isClick_=false;},get targetElement(){return this.targetElement_;},set targetElement(target){if(this.targetElement_)
 this.targetElement_.removeEventListener('mousedown',this.onMouseDown_);this.targetElement_=target;if(this.targetElement_)
 this.targetElement_.addEventListener('mousedown',this.onMouseDown_);},get defaultMode(){return this.defaultMode_;},set defaultMode(defaultMode){this.defaultMode_=defaultMode;},get settingsKey(){return this.settingsKey_;},set settingsKey(settingsKey){this.settingsKey_=settingsKey;if(!this.settingsKey_)
-return;var mode=tv.b.Settings.get(this.settingsKey_+'.mode',undefined);if(allModeInfo[mode]===undefined)
+return;var mode=tr.b.Settings.get(this.settingsKey_+'.mode',undefined);if(allModeInfo[mode]===undefined)
 mode=undefined;if((mode&this.supportedModeMask_)===0)
 mode=undefined;if(!mode)
-mode=this.defaultMode_;this.mode=mode;var pos=tv.b.Settings.get(this.settingsKey_+'.pos',undefined);if(pos)
+mode=this.defaultMode_;this.mode=mode;var pos=tr.b.Settings.get(this.settingsKey_+'.pos',undefined);if(pos)
 this.pos=pos;},get supportedModeMask(){return this.supportedModeMask_;},set supportedModeMask(supportedModeMask){if(this.mode&&(supportedModeMask&this.mode)===0)
 throw new Error('supportedModeMask must include current mode.');function createButtonForMode(mode){var button=document.createElement('div');button.mode=mode;button.title=allModeInfo[mode].title;button.classList.add('tool-button');button.classList.add(allModeInfo[mode].className);return button;}
 this.supportedModeMask_=supportedModeMask;this.buttonsEl_.textContent='';for(var modeName in MOUSE_SELECTOR_MODE){if(modeName=='ALL_MODES')
@@ -2994,34 +3065,34 @@
 var modeInfo;if(this.currentMode_===newMode)
 return;if(this.currentMode_){modeInfo=allModeInfo[this.currentMode_];var buttonEl=this.buttonsEl_.querySelector('.'+modeInfo.className);if(buttonEl)
 buttonEl.classList.remove('active');if(this.isInteracting_){var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.end);this.dispatchEvent(mouseEvent);}
-tv.b.dispatchSimpleEvent(this,modeInfo.eventNames.exit,true);}
+tr.b.dispatchSimpleEvent(this,modeInfo.eventNames.exit,true);}
 this.currentMode_=newMode;if(this.currentMode_){modeInfo=allModeInfo[this.currentMode_];var buttonEl=this.buttonsEl_.querySelector('.'+modeInfo.className);if(buttonEl)
 buttonEl.classList.add('active');this.mouseDownPos_.x=this.mousePos_.x;this.mouseDownPos_.y=this.mousePos_.y;if(!this.isInAlternativeMode_)
-tv.b.dispatchSimpleEvent(this,modeInfo.eventNames.enter,true);if(this.isInteracting_){var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.begin);this.dispatchEvent(mouseEvent);}}
+tr.b.dispatchSimpleEvent(this,modeInfo.eventNames.enter,true);if(this.isInteracting_){var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.begin);this.dispatchEvent(mouseEvent);}}
 if(this.settingsKey_&&!this.isInAlternativeMode_)
-tv.b.Settings.set(this.settingsKey_+'.mode',this.mode);},setKeyCodeForMode:function(mode,keyCode){if((mode&this.supportedModeMask_)===0)
+tr.b.Settings.set(this.settingsKey_+'.mode',this.mode);},setKeyCodeForMode:function(mode,keyCode){if((mode&this.supportedModeMask_)===0)
 throw new Error('Mode not supported');this.modeToKeyCodeMap_[mode]=keyCode;if(!this.buttonsEl_)
-return;var modeInfo=allModeInfo[mode];var buttonEl=this.buttonsEl_.querySelector('.'+modeInfo.className);if(buttonEl){buttonEl.title=modeInfo.title+' ('+String.fromCharCode(keyCode)+')';}},setKeyCodeCondition:function(callback){this.keyCodeCondition=callback;},setCurrentMousePosFromEvent_:function(e){this.mousePos_.x=e.clientX;this.mousePos_.y=e.clientY;},createEvent_:function(eventName,sourceEvent){var event=new tv.b.Event(eventName,true);event.clientX=this.mousePos_.x;event.clientY=this.mousePos_.y;event.deltaX=this.mousePos_.x-this.mouseDownPos_.x;event.deltaY=this.mousePos_.y-this.mouseDownPos_.y;event.mouseDownX=this.mouseDownPos_.x;event.mouseDownY=this.mouseDownPos_.y;event.didPreventDefault=false;event.preventDefault=function(){event.didPreventDefault=true;if(sourceEvent)
+return;var modeInfo=allModeInfo[mode];var buttonEl=this.buttonsEl_.querySelector('.'+modeInfo.className);if(buttonEl){buttonEl.title=modeInfo.title+' ('+String.fromCharCode(keyCode)+')';}},setKeyCodeCondition:function(callback){this.keyCodeCondition=callback;},setCurrentMousePosFromEvent_:function(e){this.mousePos_.x=e.clientX;this.mousePos_.y=e.clientY;},createEvent_:function(eventName,sourceEvent){var event=new tr.b.Event(eventName,true);event.clientX=this.mousePos_.x;event.clientY=this.mousePos_.y;event.deltaX=this.mousePos_.x-this.mouseDownPos_.x;event.deltaY=this.mousePos_.y-this.mouseDownPos_.y;event.mouseDownX=this.mouseDownPos_.x;event.mouseDownY=this.mouseDownPos_.y;event.didPreventDefault=false;event.preventDefault=function(){event.didPreventDefault=true;if(sourceEvent)
 sourceEvent.preventDefault();};event.stopPropagation=function(){sourceEvent.stopPropagation();};event.stopImmediatePropagation=function(){throw new Error('Not implemented');};return event;},onMouseDown_:function(e){if(e.button!==0)
-return;this.setCurrentMousePosFromEvent_(e);var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.begin,e);this.dispatchEvent(mouseEvent);this.isInteracting_=true;this.isClick_=true;tv.b.ui.trackMouseMovesUntilMouseUp(this.onMouseMove_,this.onMouseUp_);},onMouseMove_:function(e){this.setCurrentMousePosFromEvent_(e);var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.update,e);this.dispatchEvent(mouseEvent);if(this.isInteracting_)
+return;this.setCurrentMousePosFromEvent_(e);var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.begin,e);this.dispatchEvent(mouseEvent);this.isInteracting_=true;this.isClick_=true;tr.b.ui.trackMouseMovesUntilMouseUp(this.onMouseMove_,this.onMouseUp_);},onMouseMove_:function(e){this.setCurrentMousePosFromEvent_(e);var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.update,e);this.dispatchEvent(mouseEvent);if(this.isInteracting_)
 this.checkIsClick_(e);},onMouseUp_:function(e){if(e.button!==0)
 return;var mouseEvent=this.createEvent_(allModeInfo[this.mode].eventNames.end,e);mouseEvent.isClick=this.isClick_;this.dispatchEvent(mouseEvent);if(this.isClick_&&!mouseEvent.didPreventDefault)
 this.dispatchClickEvents_(e);this.isInteracting_=false;this.updateAlternativeModeState_(e);},onButtonMouseDown_:function(e){e.preventDefault();e.stopImmediatePropagation();},onButtonMouseUp_:function(e){e.preventDefault();e.stopImmediatePropagation();},onButtonPress_:function(e){this.modeBeforeAlternativeModeActivated_=undefined;this.mode=e.target.mode;e.preventDefault();},onKeyDown_:function(e){if(e.keyCode===' '.charCodeAt(0))
 this.spacePressed_=true;this.updateAlternativeModeState_(e);},onKeyUp_:function(e){if(e.keyCode===' '.charCodeAt(0))
 this.spacePressed_=false;if(this.keyCodeCondition!=undefined&&!this.keyCodeCondition()){return;}
-var didHandleKey=false;tv.b.iterItems(this.modeToKeyCodeMap_,function(modeStr,keyCode){if(e.keyCode===keyCode){this.modeBeforeAlternativeModeActivated_=undefined;var mode=parseInt(modeStr);this.mode=mode;didHandleKey=true;}},this);if(didHandleKey){e.preventDefault();e.stopPropagation();return;}
-this.updateAlternativeModeState_(e);},updateAlternativeModeState_:function(e){var shiftPressed=e.shiftKey;var spacePressed=this.spacePressed_;var cmdOrCtrlPressed=(tv.isMac&&e.metaKey)||(!tv.isMac&&e.ctrlKey);var smm=this.supportedModeMask_;var newMode;var isNewModeAnAlternativeMode=false;if(shiftPressed&&(this.modifierToModeMap_[MODIFIER.SHIFT]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.SHIFT];isNewModeAnAlternativeMode=true;}else if(spacePressed&&(this.modifierToModeMap_[MODIFIER.SPACE]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.SPACE];isNewModeAnAlternativeMode=true;}else if(cmdOrCtrlPressed&&(this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL];isNewModeAnAlternativeMode=true;}else{if(this.isInAlternativeMode_){newMode=this.modeBeforeAlternativeModeActivated_;isNewModeAnAlternativeMode=false;}else{newMode=undefined;}}
+var didHandleKey=false;tr.b.iterItems(this.modeToKeyCodeMap_,function(modeStr,keyCode){if(e.keyCode===keyCode){this.modeBeforeAlternativeModeActivated_=undefined;var mode=parseInt(modeStr);this.mode=mode;didHandleKey=true;}},this);if(didHandleKey){e.preventDefault();e.stopPropagation();return;}
+this.updateAlternativeModeState_(e);},updateAlternativeModeState_:function(e){var shiftPressed=e.shiftKey;var spacePressed=this.spacePressed_;var cmdOrCtrlPressed=(tr.isMac&&e.metaKey)||(!tr.isMac&&e.ctrlKey);var smm=this.supportedModeMask_;var newMode;var isNewModeAnAlternativeMode=false;if(shiftPressed&&(this.modifierToModeMap_[MODIFIER.SHIFT]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.SHIFT];isNewModeAnAlternativeMode=true;}else if(spacePressed&&(this.modifierToModeMap_[MODIFIER.SPACE]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.SPACE];isNewModeAnAlternativeMode=true;}else if(cmdOrCtrlPressed&&(this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL];isNewModeAnAlternativeMode=true;}else{if(this.isInAlternativeMode_){newMode=this.modeBeforeAlternativeModeActivated_;isNewModeAnAlternativeMode=false;}else{newMode=undefined;}}
 if(this.mode===newMode||newMode===undefined)
 return;if(isNewModeAnAlternativeMode)
 this.modeBeforeAlternativeModeActivated_=this.mode;this.mode=newMode;},get isInAlternativeMode_(){return!!this.modeBeforeAlternativeModeActivated_;},setModifierForAlternateMode:function(mode,modifier){this.modifierToModeMap_[modifier]=mode;},get pos(){return{x:parseInt(this.style.left),y:parseInt(this.style.top)};},set pos(pos){pos=this.constrainPositionToBounds_(pos);this.style.left=pos.x+'px';this.style.top=pos.y+'px';if(this.settingsKey_)
-tv.b.Settings.set(this.settingsKey_+'.pos',this.pos);},constrainPositionToBounds_:function(pos){var parent=this.offsetParent||document.body;var parentRect=tv.b.windowRectForElement(parent);var top=0;var bottom=parentRect.height-this.offsetHeight;var left=0;var right=parentRect.width-this.offsetWidth;var res={};res.x=Math.max(pos.x,left);res.x=Math.min(res.x,right);res.y=Math.max(pos.y,top);res.y=Math.min(res.y,bottom);return res;},onDragHandleMouseDown_:function(e){e.preventDefault();e.stopImmediatePropagation();var mouseDownPos={x:e.clientX-this.offsetLeft,y:e.clientY-this.offsetTop};tv.b.ui.trackMouseMovesUntilMouseUp(function(e){var pos={};pos.x=e.clientX-mouseDownPos.x;pos.y=e.clientY-mouseDownPos.y;this.pos=pos;}.bind(this));},checkIsClick_:function(e){if(!this.isInteracting_||!this.isClick_)
+tr.b.Settings.set(this.settingsKey_+'.pos',this.pos);},constrainPositionToBounds_:function(pos){var parent=this.offsetParent||document.body;var parentRect=tr.b.windowRectForElement(parent);var top=0;var bottom=parentRect.height-this.offsetHeight;var left=0;var right=parentRect.width-this.offsetWidth;var res={};res.x=Math.max(pos.x,left);res.x=Math.min(res.x,right);res.y=Math.max(pos.y,top);res.y=Math.min(res.y,bottom);return res;},onDragHandleMouseDown_:function(e){e.preventDefault();e.stopImmediatePropagation();var mouseDownPos={x:e.clientX-this.offsetLeft,y:e.clientY-this.offsetTop};tr.b.ui.trackMouseMovesUntilMouseUp(function(e){var pos={};pos.x=e.clientX-mouseDownPos.x;pos.y=e.clientY-mouseDownPos.y;this.pos=pos;}.bind(this));},checkIsClick_:function(e){if(!this.isInteracting_||!this.isClick_)
 return;var deltaX=this.mousePos_.x-this.mouseDownPos_.x;var deltaY=this.mousePos_.y-this.mouseDownPos_.y;var minDist=MIN_MOUSE_SELECTION_DISTANCE;if(deltaX*deltaX+deltaY*deltaY>minDist*minDist)
 this.isClick_=false;},dispatchClickEvents_:function(e){if(!this.isClick_)
-return;var eventNames=allModeInfo[MOUSE_SELECTOR_MODE.SELECTION].eventNames;var mouseEvent=this.createEvent_(eventNames.begin);this.dispatchEvent(mouseEvent);mouseEvent=this.createEvent_(eventNames.end);this.dispatchEvent(mouseEvent);}};return{MIN_MOUSE_SELECTION_DISTANCE:MIN_MOUSE_SELECTION_DISTANCE,MouseModeSelector:MouseModeSelector,MOUSE_SELECTOR_MODE:MOUSE_SELECTOR_MODE,MODIFIER:MODIFIER};});'use strict';tv.exportTo('tv.c',function(){var paletteRaw=tv.b.ui.getRawColorPalette();var palette=tv.b.ui.getColorPalette();var SelectionState=tv.c.trace_model.SelectionState;var EventPresenter={getSelectableItemColor:function(item){var colorId=item.colorId+this.getColorIdOffset_(item);return palette[colorId];},getColorIdOffset_:function(event){if(event.selectionState===SelectionState.SELECTED)
-return tv.b.ui.paletteProperties.highlightIdBoost;else if(event.selectionState===SelectionState.DIMMED)
-return tv.b.ui.paletteProperties.desaturateIdBoost;return 0;},getTextColor:function(event){if(event.selectionState===SelectionState.DIMMED)
+return;var eventNames=allModeInfo[MOUSE_SELECTOR_MODE.SELECTION].eventNames;var mouseEvent=this.createEvent_(eventNames.begin);this.dispatchEvent(mouseEvent);mouseEvent=this.createEvent_(eventNames.end);this.dispatchEvent(mouseEvent);}};return{MIN_MOUSE_SELECTION_DISTANCE:MIN_MOUSE_SELECTION_DISTANCE,MouseModeSelector:MouseModeSelector,MOUSE_SELECTOR_MODE:MOUSE_SELECTOR_MODE,MODIFIER:MODIFIER};});'use strict';tr.exportTo('tr.c',function(){var paletteRaw=tr.b.ui.getRawColorPalette();var palette=tr.b.ui.getColorPalette();var SelectionState=tr.model.SelectionState;var EventPresenter={getSelectableItemColor:function(item){var colorId=item.colorId+this.getColorIdOffset_(item);return palette[colorId];},getColorIdOffset_:function(event){if(event.selectionState===SelectionState.SELECTED)
+return tr.b.ui.paletteProperties.highlightIdBoost;else if(event.selectionState===SelectionState.DIMMED)
+return tr.b.ui.paletteProperties.desaturateIdBoost;return 0;},getTextColor:function(event){if(event.selectionState===SelectionState.DIMMED)
 return'rgb(60,60,60)';return'rgb(0,0,0)';},getSliceColorId:function(slice){return slice.colorId+this.getColorIdOffset_(slice);},getSliceAlpha:function(slice,async){var alpha=1;if(async)
-alpha*=0.3;return alpha;},getInstantSliceColor:function(instant){var colorId=instant.colorId+this.getColorIdOffset_(instant);return tv.b.ui.colorToRGBAString(paletteRaw[colorId],1.0);},getObjectInstanceColor:function(instance){var colorId=instance.colorId+this.getColorIdOffset_(instance);return tv.b.ui.colorToRGBAString(paletteRaw[colorId],0.25);},getObjectSnapshotColor:function(snapshot){var colorId=snapshot.objectInstance.colorId+this.getColorIdOffset_(snapshot);return palette[colorId];},getCounterSeriesColor:function(colorId,selectionState,opt_alphaMultiplier){var event={selectionState:selectionState};return tv.b.ui.colorToRGBAString(paletteRaw[colorId+this.getColorIdOffset_(event)],(opt_alphaMultiplier!==undefined?opt_alphaMultiplier:1.0));},getBarSnapshotColor:function(snapshot,offset){var colorId=(snapshot.objectInstance.colorId+offset)%tv.b.ui.paletteProperties.numGeneralPurposeColorIds;colorId+=this.getColorIdOffset_(snapshot);return tv.b.ui.colorToRGBAString(paletteRaw[colorId],1.0);}};return{EventPresenter:EventPresenter};});'use strict';tv.exportTo('tv.c',function(){var elidedTitleCacheDict={};var elidedTitleCache=new ElidedTitleCache();function ElidedTitleCache(){this.textWidthMap={};}
+alpha*=0.3;return alpha;},getInstantSliceColor:function(instant){var colorId=instant.colorId+this.getColorIdOffset_(instant);return tr.b.ui.colorToRGBAString(paletteRaw[colorId],1.0);},getObjectInstanceColor:function(instance){var colorId=instance.colorId+this.getColorIdOffset_(instance);return tr.b.ui.colorToRGBAString(paletteRaw[colorId],0.25);},getObjectSnapshotColor:function(snapshot){var colorId=snapshot.objectInstance.colorId+this.getColorIdOffset_(snapshot);return palette[colorId];},getCounterSeriesColor:function(colorId,selectionState,opt_alphaMultiplier){var event={selectionState:selectionState};return tr.b.ui.colorToRGBAString(paletteRaw[colorId+this.getColorIdOffset_(event)],(opt_alphaMultiplier!==undefined?opt_alphaMultiplier:1.0));},getBarSnapshotColor:function(snapshot,offset){var colorId=(snapshot.objectInstance.colorId+offset)%tr.b.ui.paletteProperties.numGeneralPurposeColorIds;colorId+=this.getColorIdOffset_(snapshot);return tr.b.ui.colorToRGBAString(paletteRaw[colorId],1.0);}};return{EventPresenter:EventPresenter};});'use strict';tr.exportTo('tr.c',function(){var elidedTitleCacheDict={};var elidedTitleCache=new ElidedTitleCache();function ElidedTitleCache(){this.textWidthMap={};}
 ElidedTitleCache.prototype={get:function(ctx,pixWidth,title,width,sliceDuration){var elidedDict=elidedTitleCacheDict[title];if(!elidedDict){elidedDict={};elidedTitleCacheDict[title]=elidedDict;}
 var elidedDictForPixWidth=elidedDict[pixWidth];if(!elidedDictForPixWidth){elidedDict[pixWidth]={};elidedDictForPixWidth=elidedDict[pixWidth];}
 var stringWidthPair=elidedDictForPixWidth[sliceDuration];if(stringWidthPair===undefined){var newtitle=title;var elided=false;while(this.labelWidthWorld(ctx,newtitle,pixWidth)>sliceDuration){if(newtitle.length*0.75<1)
@@ -3030,60 +3101,60 @@
 newtitle=newtitle.substring(0,newtitle.length-3)+'...';stringWidthPair=new ElidedStringWidthPair(newtitle,this.labelWidth(ctx,newtitle));elidedDictForPixWidth[sliceDuration]=stringWidthPair;}
 return stringWidthPair;},quickMeasureText_:function(ctx,text){var w=this.textWidthMap[text];if(!w){w=ctx.measureText(text).width;this.textWidthMap[text]=w;}
 return w;},labelWidth:function(ctx,title){return this.quickMeasureText_(ctx,title)+2;},labelWidthWorld:function(ctx,title,pixWidth){return this.labelWidth(ctx,title)*pixWidth;}};function ElidedStringWidthPair(string,width){this.string=string;this.width=width;}
-return{ElidedTitleCache:ElidedTitleCache};});'use strict';tv.exportTo('tv.c',function(){var elidedTitleCache=new tv.c.ElidedTitleCache();var palette=tv.b.ui.getColorPalette();var EventPresenter=tv.c.EventPresenter;var blackColorId=tv.b.ui.getColorIdForReservedName('black');var THIN_SLICE_HEIGHT=4;var SLICE_WAITING_WIDTH_DRAW_THRESHOLD=3;var SLICE_ACTIVE_WIDTH_DRAW_THRESHOLD=1;var SHOULD_ELIDE_TEXT=true;function drawLine(ctx,x1,y1,x2,y2){ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);}
+return{ElidedTitleCache:ElidedTitleCache};});'use strict';tr.exportTo('tr.c',function(){var elidedTitleCache=new tr.c.ElidedTitleCache();var palette=tr.b.ui.getColorPalette();var EventPresenter=tr.c.EventPresenter;var blackColorId=tr.b.ui.getColorIdForReservedName('black');var THIN_SLICE_HEIGHT=4;var SLICE_WAITING_WIDTH_DRAW_THRESHOLD=3;var SLICE_ACTIVE_WIDTH_DRAW_THRESHOLD=1;var SHOULD_ELIDE_TEXT=true;function drawLine(ctx,x1,y1,x2,y2){ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);}
 function drawTriangle(ctx,x1,y1,x2,y2,x3,y3){ctx.beginPath();ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);ctx.lineTo(x3,y3);ctx.closePath();}
 function drawArrow(ctx,x1,y1,x2,y2,arrowLength,arrowWidth){var dx=x2-x1;var dy=y2-y1;var len=Math.sqrt(dx*dx+dy*dy);var perc=(len-arrowLength)/len;var bx=x1+perc*dx;var by=y1+perc*dy;var ux=dx/len;var uy=dy/len;var ax=uy*arrowWidth;var ay=-ux*arrowWidth;ctx.beginPath();drawLine(ctx,x1,y1,x2,y2);ctx.stroke();drawTriangle(ctx,bx+ax,by+ay,x2,y2,bx-ax,by-ay);ctx.fill();}
 function drawSlices(ctx,dt,viewLWorld,viewRWorld,viewHeight,slices,async){var pixelRatio=window.devicePixelRatio||1;var pixWidth=dt.xViewVectorToWorld(1);var height=viewHeight*pixelRatio;var darkRectHeight=THIN_SLICE_HEIGHT*pixelRatio;if(height<darkRectHeight)
-darkRectHeight=0;var lightRectHeight=height-darkRectHeight;ctx.save();dt.applyTransformToCanvas(ctx);var tr=new tv.c.FastRectRenderer(ctx,2*pixWidth,2*pixWidth,palette);tr.setYandH(0,height);var lowSlice=tv.b.findLowIndexInSortedArray(slices,function(slice){return slice.start+slice.duration;},viewLWorld);var hadTopLevel=false;for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];var x=slice.start;if(x>viewRWorld)
+darkRectHeight=0;var lightRectHeight=height-darkRectHeight;ctx.save();dt.applyTransformToCanvas(ctx);var rect=new tr.c.FastRectRenderer(ctx,2*pixWidth,2*pixWidth,palette);rect.setYandH(0,height);var lowSlice=tr.b.findLowIndexInSortedArray(slices,function(slice){return slice.start+slice.duration;},viewLWorld);var hadTopLevel=false;for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];var x=slice.start;if(x>viewRWorld)
 break;var w=pixWidth;if(slice.duration>0){w=Math.max(slice.duration,0.000001);if(w<pixWidth)
 w=pixWidth;}
-var colorId=EventPresenter.getSliceColorId(slice);var alpha=EventPresenter.getSliceAlpha(slice,async);var lightAlpha=alpha*0.70;if(slice.isTopLevel){tr.setYandH(3,height-3);hadTopLevel=true;}else{tr.setYandH(0,height);}
-if(!slice.cpuDuration){tr.fillRect(x,w,colorId,alpha);continue;}
+var colorId=EventPresenter.getSliceColorId(slice);var alpha=EventPresenter.getSliceAlpha(slice,async);var lightAlpha=alpha*0.70;if(slice.isTopLevel){rect.setYandH(3,height-3);hadTopLevel=true;}else{rect.setYandH(0,height);}
+if(!slice.cpuDuration){rect.fillRect(x,w,colorId,alpha);continue;}
 var activeWidth=w*(slice.cpuDuration/slice.duration);var waitingWidth=w-activeWidth;if(activeWidth<SLICE_ACTIVE_WIDTH_DRAW_THRESHOLD*pixWidth){activeWidth=0;waitingWidth=w;}
 if(waitingWidth<SLICE_WAITING_WIDTH_DRAW_THRESHOLD*pixWidth){activeWidth=w;waitingWidth=0;}
-if(activeWidth>0){tr.fillRect(x,activeWidth,colorId,alpha);}
-if(waitingWidth>0){tr.setYandH(0,lightRectHeight);tr.fillRect(x+activeWidth-pixWidth,waitingWidth+pixWidth,colorId,lightAlpha);tr.setYandH(lightRectHeight,darkRectHeight);tr.fillRect(x+activeWidth-pixWidth,waitingWidth+pixWidth,colorId,alpha);tr.setYandH(0,height);}}
-tr.flush();if(async&&hadTopLevel){tr.setYandH(2,1);for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];var x=slice.start;if(x>viewRWorld)
+if(activeWidth>0){rect.fillRect(x,activeWidth,colorId,alpha);}
+if(waitingWidth>0){rect.setYandH(0,lightRectHeight);rect.fillRect(x+activeWidth-pixWidth,waitingWidth+pixWidth,colorId,lightAlpha);rect.setYandH(lightRectHeight,darkRectHeight);rect.fillRect(x+activeWidth-pixWidth,waitingWidth+pixWidth,colorId,alpha);rect.setYandH(0,height);}}
+rect.flush();if(async&&hadTopLevel){rect.setYandH(2,1);for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];var x=slice.start;if(x>viewRWorld)
 break;if(!slice.isTopLevel)
 continue;var w=pixWidth;if(slice.duration>0){w=Math.max(slice.duration,0.000001);if(w<pixWidth)
 w=pixWidth;}
-tr.fillRect(x,w,blackColorId,0.7);}
-tr.flush();}
+rect.fillRect(x,w,blackColorId,0.7);}
+rect.flush();}
 ctx.restore();}
-function drawInstantSlicesAsLines(ctx,dt,viewLWorld,viewRWorld,viewHeight,slices,lineWidthInPixels){var pixelRatio=window.devicePixelRatio||1;var height=viewHeight*pixelRatio;var pixWidth=dt.xViewVectorToWorld(1);ctx.save();ctx.lineWidth=pixWidth*lineWidthInPixels*pixelRatio;dt.applyTransformToCanvas(ctx);ctx.beginPath();var lowSlice=tv.b.findLowIndexInSortedArray(slices,function(slice){return slice.start;},viewLWorld);for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];var x=slice.start;if(x>viewRWorld)
+function drawInstantSlicesAsLines(ctx,dt,viewLWorld,viewRWorld,viewHeight,slices,lineWidthInPixels){var pixelRatio=window.devicePixelRatio||1;var height=viewHeight*pixelRatio;var pixWidth=dt.xViewVectorToWorld(1);ctx.save();ctx.lineWidth=pixWidth*lineWidthInPixels*pixelRatio;dt.applyTransformToCanvas(ctx);ctx.beginPath();var lowSlice=tr.b.findLowIndexInSortedArray(slices,function(slice){return slice.start;},viewLWorld);for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];var x=slice.start;if(x>viewRWorld)
 break;ctx.strokeStyle=EventPresenter.getInstantSliceColor(slice);ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,height);ctx.stroke();}
 ctx.restore();}
 function drawLabels(ctx,dt,viewLWorld,viewRWorld,slices,async,fontSize,yOffset){var pixelRatio=window.devicePixelRatio||1;var pixWidth=dt.xViewVectorToWorld(1);ctx.save();ctx.textAlign='center';ctx.textBaseline='top';ctx.font=(fontSize*pixelRatio)+'px sans-serif';if(async)
-ctx.font='italic '+ctx.font;var cY=yOffset*pixelRatio;var lowSlice=tv.b.findLowIndexInSortedArray(slices,function(slice){return slice.start+slice.duration;},viewLWorld);var quickDiscardThresshold=pixWidth*20;for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];if(slice.start>viewRWorld)
+ctx.font='italic '+ctx.font;var cY=yOffset*pixelRatio;var lowSlice=tr.b.findLowIndexInSortedArray(slices,function(slice){return slice.start+slice.duration;},viewLWorld);var quickDiscardThresshold=pixWidth*20;for(var i=lowSlice;i<slices.length;++i){var slice=slices[i];if(slice.start>viewRWorld)
 break;if(slice.duration<=quickDiscardThresshold)
 continue;var title=slice.title+
 (slice.didNotFinish?' (Did Not Finish)':'');var drawnTitle=title;var drawnWidth=elidedTitleCache.labelWidth(ctx,drawnTitle);var fullLabelWidth=elidedTitleCache.labelWidthWorld(ctx,drawnTitle,pixWidth);if(SHOULD_ELIDE_TEXT&&fullLabelWidth>slice.duration){var elidedValues=elidedTitleCache.get(ctx,pixWidth,drawnTitle,drawnWidth,slice.duration);drawnTitle=elidedValues.string;drawnWidth=elidedValues.width;}
 if(drawnWidth*pixWidth<slice.duration){ctx.fillStyle=EventPresenter.getTextColor(slice);var cX=dt.xWorldToView(slice.start+0.5*slice.duration);ctx.fillText(drawnTitle,cX,cY,drawnWidth);}}
 ctx.restore();}
-return{drawSlices:drawSlices,drawInstantSlicesAsLines:drawInstantSlicesAsLines,drawLabels:drawLabels,drawLine:drawLine,drawTriangle:drawTriangle,drawArrow:drawArrow,elidedTitleCache_:elidedTitleCache,THIN_SLICE_HEIGHT:THIN_SLICE_HEIGHT};});'use strict';tv.exportTo('tv.c',function(){function SnapIndicator(y,height){this.y=y;this.height=height;}
-function TimelineInterestRange(vp){this.viewport_=vp;this.range_=new tv.b.Range();this.leftSelected_=false;this.rightSelected_=false;this.leftSnapIndicator_=undefined;this.rightSnapIndicator_=undefined;}
-TimelineInterestRange.prototype={get isEmpty(){return this.range_.isEmpty;},reset:function(){this.range_.reset();this.leftSelected_=false;this.rightSelected_=false;this.leftSnapIndicator_=undefined;this.rightSnapIndicator_=undefined;this.viewport_.dispatchChangeEvent();},get min(){return this.range_.min;},set min(min){this.range_.min=min;this.viewport_.dispatchChangeEvent();},get max(){return this.range_.max;},set max(max){this.range_.max=max;this.viewport_.dispatchChangeEvent();},set:function(range){this.range_.reset();this.range_.addRange(range);this.viewport_.dispatchChangeEvent();},setMinAndMax:function(min,max){this.range_.min=min;this.range_.max=max;this.viewport_.dispatchChangeEvent();},get range(){return this.range_.range;},asRangeObject:function(){var range=new tv.b.Range();range.addRange(this.range_);return range;},get leftSelected(){return this.leftSelected_;},set leftSelected(leftSelected){if(this.leftSelected_==leftSelected)
+return{drawSlices:drawSlices,drawInstantSlicesAsLines:drawInstantSlicesAsLines,drawLabels:drawLabels,drawLine:drawLine,drawTriangle:drawTriangle,drawArrow:drawArrow,elidedTitleCache_:elidedTitleCache,THIN_SLICE_HEIGHT:THIN_SLICE_HEIGHT};});'use strict';tr.exportTo('tr.c',function(){function SnapIndicator(y,height){this.y=y;this.height=height;}
+function TimelineInterestRange(vp){this.viewport_=vp;this.range_=new tr.b.Range();this.leftSelected_=false;this.rightSelected_=false;this.leftSnapIndicator_=undefined;this.rightSnapIndicator_=undefined;}
+TimelineInterestRange.prototype={get isEmpty(){return this.range_.isEmpty;},reset:function(){this.range_.reset();this.leftSelected_=false;this.rightSelected_=false;this.leftSnapIndicator_=undefined;this.rightSnapIndicator_=undefined;this.viewport_.dispatchChangeEvent();},get min(){return this.range_.min;},set min(min){this.range_.min=min;this.viewport_.dispatchChangeEvent();},get max(){return this.range_.max;},set max(max){this.range_.max=max;this.viewport_.dispatchChangeEvent();},set:function(range){this.range_.reset();this.range_.addRange(range);this.viewport_.dispatchChangeEvent();},setMinAndMax:function(min,max){this.range_.min=min;this.range_.max=max;this.viewport_.dispatchChangeEvent();},get range(){return this.range_.range;},asRangeObject:function(){var range=new tr.b.Range();range.addRange(this.range_);return range;},get leftSelected(){return this.leftSelected_;},set leftSelected(leftSelected){if(this.leftSelected_==leftSelected)
 return;this.leftSelected_=leftSelected;this.viewport_.dispatchChangeEvent();},get rightSelected(){return this.rightSelected_;},set rightSelected(rightSelected){if(this.rightSelected_==rightSelected)
 return;this.rightSelected_=rightSelected;this.viewport_.dispatchChangeEvent();},get leftSnapIndicator(){return this.leftSnapIndicator_;},set leftSnapIndicator(leftSnapIndicator){this.leftSnapIndicator_=leftSnapIndicator;this.viewport_.dispatchChangeEvent();},get rightSnapIndicator(){return this.rightSnapIndicator_;},set rightSnapIndicator(rightSnapIndicator){this.rightSnapIndicator_=rightSnapIndicator;this.viewport_.dispatchChangeEvent();},draw:function(ctx,viewLWorld,viewRWorld){if(this.range_.isEmpty)
 return;var dt=this.viewport_.currentDisplayTransform;var markerLWorld=this.min;var markerRWorld=this.max;var markerLView=Math.round(dt.xWorldToView(markerLWorld));var markerRView=Math.round(dt.xWorldToView(markerRWorld));ctx.fillStyle='rgba(0, 0, 0, 0.2)';if(markerLWorld>viewLWorld){ctx.fillRect(dt.xWorldToView(viewLWorld),0,markerLView,ctx.canvas.height);}
 if(markerRWorld<viewRWorld){ctx.fillRect(markerRView,0,dt.xWorldToView(viewRWorld),ctx.canvas.height);}
 var pixelRatio=window.devicePixelRatio||1;ctx.lineWidth=Math.round(pixelRatio);if(this.range_.range>0){this.drawLine_(ctx,viewLWorld,viewRWorld,ctx.canvas.height,this.min,this.leftSelected_);this.drawLine_(ctx,viewLWorld,viewRWorld,ctx.canvas.height,this.max,this.rightSelected_);}else{this.drawLine_(ctx,viewLWorld,viewRWorld,ctx.canvas.height,this.min,this.leftSelected_||this.rightSelected_);}
 ctx.lineWidth=1;},drawLine_:function(ctx,viewLWorld,viewRWorld,height,ts,selected){if(ts<viewLWorld||ts>=viewRWorld)
-return;var dt=this.viewport_.currentDisplayTransform;var viewX=Math.round(dt.xWorldToView(ts));ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();tv.c.drawLine(ctx,viewX,0,viewX,height);if(selected)
+return;var dt=this.viewport_.currentDisplayTransform;var viewX=Math.round(dt.xWorldToView(ts));ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();tr.c.drawLine(ctx,viewX,0,viewX,height);if(selected)
 ctx.strokeStyle='rgb(255, 0, 0)';else
 ctx.strokeStyle='rgb(0, 0, 0)';ctx.stroke();ctx.restore();},drawIndicators:function(ctx,viewLWorld,viewRWorld){if(this.leftSnapIndicator_){this.drawIndicator_(ctx,viewLWorld,viewRWorld,this.range_.min,this.leftSnapIndicator_,this.leftSelected_);}
 if(this.rightSnapIndicator_){this.drawIndicator_(ctx,viewLWorld,viewRWorld,this.range_.max,this.rightSnapIndicator_,this.rightSelected_);}},drawIndicator_:function(ctx,viewLWorld,viewRWorld,xWorld,si,selected){var dt=this.viewport_.currentDisplayTransform;var viewX=Math.round(dt.xWorldToView(xWorld));ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);var pixelRatio=window.devicePixelRatio||1;var viewY=si.y*devicePixelRatio;var viewHeight=si.height*devicePixelRatio;var arrowSize=4*pixelRatio;if(selected)
 ctx.fillStyle='rgb(255, 0, 0)';else
-ctx.fillStyle='rgb(0, 0, 0)';tv.c.drawTriangle(ctx,viewX-arrowSize*0.75,viewY,viewX+arrowSize*0.75,viewY,viewX,viewY+arrowSize);ctx.fill();tv.c.drawTriangle(ctx,viewX-arrowSize*0.75,viewY+viewHeight,viewX+arrowSize*0.75,viewY+viewHeight,viewX,viewY+viewHeight-arrowSize);ctx.fill();ctx.restore();}};return{SnapIndicator:SnapIndicator,TimelineInterestRange:TimelineInterestRange};});'use strict';tv.exportTo('tv.c',function(){function TimelineDisplayTransform(opt_that){if(opt_that){this.set(opt_that);return;}
+ctx.fillStyle='rgb(0, 0, 0)';tr.c.drawTriangle(ctx,viewX-arrowSize*0.75,viewY,viewX+arrowSize*0.75,viewY,viewX,viewY+arrowSize);ctx.fill();tr.c.drawTriangle(ctx,viewX-arrowSize*0.75,viewY+viewHeight,viewX+arrowSize*0.75,viewY+viewHeight,viewX,viewY+viewHeight-arrowSize);ctx.fill();ctx.restore();}};return{SnapIndicator:SnapIndicator,TimelineInterestRange:TimelineInterestRange};});'use strict';tr.exportTo('tr.c',function(){function TimelineDisplayTransform(opt_that){if(opt_that){this.set(opt_that);return;}
 this.scaleX=1;this.panX=0;this.panY=0;}
 TimelineDisplayTransform.prototype={set:function(that){this.scaleX=that.scaleX;this.panX=that.panX;this.panY=that.panY;},clone:function(){return new TimelineDisplayTransform(this);},equals:function(that){var eq=true;if(that===undefined||that===null)
 return false;eq&=this.panX===that.panX;eq&=this.panY===that.panY;eq&=this.scaleX===that.scaleX;return!!eq;},almostEquals:function(that){var eq=true;if(that===undefined||that===null)
 return false;eq&=Math.abs(this.panX-that.panX)<0.001;eq&=Math.abs(this.panY-that.panY)<0.001;eq&=Math.abs(this.scaleX-that.scaleX)<0.001;return!!eq;},incrementPanXInViewUnits:function(xDeltaView){this.panX+=this.xViewVectorToWorld(xDeltaView);},xPanWorldPosToViewPos:function(worldX,viewX,viewWidth){if(typeof viewX=='string'){if(viewX==='left'){viewX=0;}else if(viewX==='center'){viewX=viewWidth/2;}else if(viewX==='right'){viewX=viewWidth-1;}else{throw new Error('viewX must be left|center|right or number.');}}
 this.panX=(viewX/this.scaleX)-worldX;},xPanWorldBoundsIntoView:function(worldMin,worldMax,viewWidth){if(this.xWorldToView(worldMin)<0)
 this.xPanWorldPosToViewPos(worldMin,'left',viewWidth);else if(this.xWorldToView(worldMax)>viewWidth)
-this.xPanWorldPosToViewPos(worldMax,'right',viewWidth);},xSetWorldBounds:function(worldMin,worldMax,viewWidth){var worldWidth=worldMax-worldMin;var scaleX=viewWidth/worldWidth;var panX=-worldMin;this.setPanAndScale(panX,scaleX);},setPanAndScale:function(p,s){this.scaleX=s;this.panX=p;},xWorldToView:function(x){return(x+this.panX)*this.scaleX;},xWorldVectorToView:function(x){return x*this.scaleX;},xViewToWorld:function(x){return(x/this.scaleX)-this.panX;},xViewVectorToWorld:function(x){return x/this.scaleX;},applyTransformToCanvas:function(ctx){ctx.transform(this.scaleX,0,0,1,this.panX*this.scaleX,0);}};return{TimelineDisplayTransform:TimelineDisplayTransform};});'use strict';tv.exportTo('tv.b.ui',function(){function Animation(){}
-Animation.prototype={canTakeOverFor:function(existingAnimation){throw new Error('Not implemented');},takeOverFor:function(existingAnimation,newStartTimestamp,target){throw new Error('Not implemented');},start:function(timestamp,target){throw new Error('Not implemented');},didStopEarly:function(timestamp,target,willBeTakenOverByAnotherAnimation){},tick:function(timestamp,target){throw new Error('Not implemented');}};return{Animation:Animation};});'use strict';tv.exportTo('tv.b.ui',function(){function AnimationController(){tv.b.EventTarget.call(this);this.target_=undefined;this.activeAnimation_=undefined;this.tickScheduled_=false;}
-AnimationController.prototype={__proto__:tv.b.EventTarget.prototype,get target(){return this.target_;},set target(target){if(this.activeAnimation_)
+this.xPanWorldPosToViewPos(worldMax,'right',viewWidth);},xSetWorldBounds:function(worldMin,worldMax,viewWidth){var worldWidth=worldMax-worldMin;var scaleX=viewWidth/worldWidth;var panX=-worldMin;this.setPanAndScale(panX,scaleX);},setPanAndScale:function(p,s){this.scaleX=s;this.panX=p;},xWorldToView:function(x){return(x+this.panX)*this.scaleX;},xWorldVectorToView:function(x){return x*this.scaleX;},xViewToWorld:function(x){return(x/this.scaleX)-this.panX;},xViewVectorToWorld:function(x){return x/this.scaleX;},applyTransformToCanvas:function(ctx){ctx.transform(this.scaleX,0,0,1,this.panX*this.scaleX,0);}};return{TimelineDisplayTransform:TimelineDisplayTransform};});'use strict';tr.exportTo('tr.b.ui',function(){function Animation(){}
+Animation.prototype={canTakeOverFor:function(existingAnimation){throw new Error('Not implemented');},takeOverFor:function(existingAnimation,newStartTimestamp,target){throw new Error('Not implemented');},start:function(timestamp,target){throw new Error('Not implemented');},didStopEarly:function(timestamp,target,willBeTakenOverByAnotherAnimation){},tick:function(timestamp,target){throw new Error('Not implemented');}};return{Animation:Animation};});'use strict';tr.exportTo('tr.b.ui',function(){function AnimationController(){tr.b.EventTarget.call(this);this.target_=undefined;this.activeAnimation_=undefined;this.tickScheduled_=false;}
+AnimationController.prototype={__proto__:tr.b.EventTarget.prototype,get target(){return this.target_;},set target(target){if(this.activeAnimation_)
 throw new Error('Cannot change target while animation is running.');if(target.cloneAnimationState===undefined||typeof target.cloneAnimationState!=='function')
 throw new Error('target must have a cloneAnimationState function');this.target_=target;},get activeAnimation(){return this.activeAnimation_;},get hasActiveAnimation(){return!!this.activeAnimation_;},queueAnimation:function(animation,opt_now){if(this.target_===undefined)
 throw new Error('Cannot queue animations without a target');var now;if(opt_now!==undefined)
@@ -3092,25 +3163,25 @@
 this.activeAnimation_=undefined;}
 if(this.activeAnimation_){if(animation.canTakeOverFor(this.activeAnimation_)){this.activeAnimation_.didStopEarly(now,this.target_,true);animation.takeOverFor(this.activeAnimation_,now,this.target_);}else{this.activeAnimation_.didStopEarly(now,this.target_,false);}}
 this.activeAnimation_=animation;this.activeAnimation_.start(now,this.target_);if(this.tickScheduled_)
-return;this.tickScheduled_=true;tv.b.requestAnimationFrame(this.tickActiveAnimation_,this);},cancelActiveAnimation:function(opt_now){if(!this.activeAnimation_)
+return;this.tickScheduled_=true;tr.b.requestAnimationFrame(this.tickActiveAnimation_,this);},cancelActiveAnimation:function(opt_now){if(!this.activeAnimation_)
 return;var now;if(opt_now!==undefined)
 now=opt_now;else
 now=window.performance.now();this.activeAnimation_.didStopEarly(now,this.target_,false);this.activeAnimation_=undefined;},tickActiveAnimation_:function(frameBeginTime){this.tickScheduled_=false;if(!this.activeAnimation_)
 return;if(this.target_===undefined){this.activeAnimation_.didStopEarly(frameBeginTime,this.target_,false);return;}
 var oldTargetState=this.target_.cloneAnimationState();var done=this.activeAnimation_.tick(frameBeginTime,this.target_);if(done)
-this.activeAnimation_=undefined;if(this.activeAnimation_){this.tickScheduled_=true;tv.b.requestAnimationFrame(this.tickActiveAnimation_,this);}
-if(oldTargetState){var e=new Event('didtick');e.oldTargetState=oldTargetState;this.dispatchEvent(e,false,false);}}};return{AnimationController:AnimationController};});'use strict';tv.exportTo('tv.c',function(){var TimelineDisplayTransform=tv.c.TimelineDisplayTransform;var TimelineInterestRange=tv.c.TimelineInterestRange;function ContainerToTrackObj(){this.stableIdToTrackMap_={};}
+this.activeAnimation_=undefined;if(this.activeAnimation_){this.tickScheduled_=true;tr.b.requestAnimationFrame(this.tickActiveAnimation_,this);}
+if(oldTargetState){var e=new Event('didtick');e.oldTargetState=oldTargetState;this.dispatchEvent(e,false,false);}}};return{AnimationController:AnimationController};});'use strict';tr.exportTo('tr.c',function(){var TimelineDisplayTransform=tr.c.TimelineDisplayTransform;var TimelineInterestRange=tr.c.TimelineInterestRange;function ContainerToTrackObj(){this.stableIdToTrackMap_={};}
 ContainerToTrackObj.prototype={addContainer:function(container,track){if(!track)
 throw new Error('Must provide a track.');this.stableIdToTrackMap_[container.stableId]=track;},clearMap:function(){this.stableIdToTrackMap_={};},getTrackByStableId:function(stableId){return this.stableIdToTrackMap_[stableId];}};function TimelineViewport(parentEl){this.parentEl_=parentEl;this.modelTrackContainer_=undefined;this.currentDisplayTransform_=new TimelineDisplayTransform();this.initAnimationController_();this.showFlowEvents_=false;this.highlightVSync_=false;this.highDetails_=false;this.gridTimebase_=0;this.gridStep_=1000/60;this.gridEnabled_=false;this.hasCalledSetupFunction_=false;this.onResize_=this.onResize_.bind(this);this.onModelTrackControllerScroll_=this.onModelTrackControllerScroll_.bind(this);this.checkForAttachInterval_=setInterval(this.checkForAttach_.bind(this),250);this.majorMarkPositions=[];this.interestRange_=new TimelineInterestRange(this);this.eventToTrackMap_={};this.containerToTrackObj=new ContainerToTrackObj();}
-TimelineViewport.prototype={__proto__:tv.b.EventTarget.prototype,setWhenPossible:function(fn){this.pendingSetFunction_=fn;},get isAttachedToDocumentOrInTestMode(){if(this.parentEl_===undefined)
-return;return tv.b.ui.isElementAttachedToDocument(this.parentEl_);},onResize_:function(){this.dispatchChangeEvent();},checkForAttach_:function(){if(!this.isAttachedToDocumentOrInTestMode||this.clientWidth==0)
+TimelineViewport.prototype={__proto__:tr.b.EventTarget.prototype,setWhenPossible:function(fn){this.pendingSetFunction_=fn;},get isAttachedToDocumentOrInTestMode(){if(this.parentEl_===undefined)
+return;return tr.b.ui.isElementAttachedToDocument(this.parentEl_);},onResize_:function(){this.dispatchChangeEvent();},checkForAttach_:function(){if(!this.isAttachedToDocumentOrInTestMode||this.clientWidth==0)
 return;if(!this.iframe_){this.iframe_=document.createElement('iframe');this.iframe_.style.cssText='position:absolute;width:100%;height:0;border:0;visibility:hidden;';this.parentEl_.appendChild(this.iframe_);this.iframe_.contentWindow.addEventListener('resize',this.onResize_);}
 var curSize=this.parentEl_.clientWidth+'x'+
 this.parentEl_.clientHeight;if(this.pendingSetFunction_){this.lastSize_=curSize;try{this.pendingSetFunction_();}catch(ex){console.log('While running setWhenPossible:',ex.message?ex.message+'\n'+ex.stack:ex.stack);}
 this.pendingSetFunction_=undefined;}
-window.clearInterval(this.checkForAttachInterval_);this.checkForAttachInterval_=undefined;},dispatchChangeEvent:function(){tv.b.dispatchSimpleEvent(this,'change');},detach:function(){if(this.checkForAttachInterval_){window.clearInterval(this.checkForAttachInterval_);this.checkForAttachInterval_=undefined;}
-if(this.iframe_){this.iframe_.removeEventListener('resize',this.onResize_);this.parentEl_.removeChild(this.iframe_);}},initAnimationController_:function(){this.dtAnimationController_=new tv.b.ui.AnimationController();this.dtAnimationController_.addEventListener('didtick',function(e){this.onCurentDisplayTransformChange_(e.oldTargetState);}.bind(this));var that=this;this.dtAnimationController_.target={get panX(){return that.currentDisplayTransform_.panX;},set panX(panX){that.currentDisplayTransform_.panX=panX;},get panY(){return that.currentDisplayTransform_.panY;},set panY(panY){that.currentDisplayTransform_.panY=panY;},get scaleX(){return that.currentDisplayTransform_.scaleX;},set scaleX(scaleX){that.currentDisplayTransform_.scaleX=scaleX;},cloneAnimationState:function(){return that.currentDisplayTransform_.clone();},xPanWorldPosToViewPos:function(xWorld,xView){that.currentDisplayTransform_.xPanWorldPosToViewPos(xWorld,xView,that.modelTrackContainer_.canvas.clientWidth);}};},get currentDisplayTransform(){return this.currentDisplayTransform_;},setDisplayTransformImmediately:function(displayTransform){this.dtAnimationController_.cancelActiveAnimation();var oldDisplayTransform=this.dtAnimationController_.target.cloneAnimationState();this.currentDisplayTransform_.set(displayTransform);this.onCurentDisplayTransformChange_(oldDisplayTransform);},queueDisplayTransformAnimation:function(animation){if(!(animation instanceof tv.b.ui.Animation))
-throw new Error('animation must be instanceof tv.b.ui.Animation');this.dtAnimationController_.queueAnimation(animation);},onCurentDisplayTransformChange_:function(oldDisplayTransform){if(this.modelTrackContainer_){this.currentDisplayTransform.panY=tv.b.clamp(this.currentDisplayTransform.panY,0,this.modelTrackContainer_.scrollHeight-
+window.clearInterval(this.checkForAttachInterval_);this.checkForAttachInterval_=undefined;},dispatchChangeEvent:function(){tr.b.dispatchSimpleEvent(this,'change');},detach:function(){if(this.checkForAttachInterval_){window.clearInterval(this.checkForAttachInterval_);this.checkForAttachInterval_=undefined;}
+if(this.iframe_){this.iframe_.removeEventListener('resize',this.onResize_);this.parentEl_.removeChild(this.iframe_);}},initAnimationController_:function(){this.dtAnimationController_=new tr.b.ui.AnimationController();this.dtAnimationController_.addEventListener('didtick',function(e){this.onCurentDisplayTransformChange_(e.oldTargetState);}.bind(this));var that=this;this.dtAnimationController_.target={get panX(){return that.currentDisplayTransform_.panX;},set panX(panX){that.currentDisplayTransform_.panX=panX;},get panY(){return that.currentDisplayTransform_.panY;},set panY(panY){that.currentDisplayTransform_.panY=panY;},get scaleX(){return that.currentDisplayTransform_.scaleX;},set scaleX(scaleX){that.currentDisplayTransform_.scaleX=scaleX;},cloneAnimationState:function(){return that.currentDisplayTransform_.clone();},xPanWorldPosToViewPos:function(xWorld,xView){that.currentDisplayTransform_.xPanWorldPosToViewPos(xWorld,xView,that.modelTrackContainer_.canvas.clientWidth);}};},get currentDisplayTransform(){return this.currentDisplayTransform_;},setDisplayTransformImmediately:function(displayTransform){this.dtAnimationController_.cancelActiveAnimation();var oldDisplayTransform=this.dtAnimationController_.target.cloneAnimationState();this.currentDisplayTransform_.set(displayTransform);this.onCurentDisplayTransformChange_(oldDisplayTransform);},queueDisplayTransformAnimation:function(animation){if(!(animation instanceof tr.b.ui.Animation))
+throw new Error('animation must be instanceof tr.b.ui.Animation');this.dtAnimationController_.queueAnimation(animation);},onCurentDisplayTransformChange_:function(oldDisplayTransform){if(this.modelTrackContainer_){this.currentDisplayTransform.panY=tr.b.clamp(this.currentDisplayTransform.panY,0,this.modelTrackContainer_.scrollHeight-
 this.modelTrackContainer_.clientHeight);}
 var changed=!this.currentDisplayTransform.equals(oldDisplayTransform);var yChanged=this.currentDisplayTransform.panY!==oldDisplayTransform.panY;if(yChanged)
 this.modelTrackContainer_.scrollTop=this.currentDisplayTransform.panY;if(changed)
@@ -3118,24 +3189,24 @@
 this.dtAnimationController_.cancelActiveAnimation();var panY=this.modelTrackContainer_.scrollTop;this.currentDisplayTransform_.panY=panY;},get modelTrackContainer(){return this.modelTrackContainer_;},set modelTrackContainer(m){if(this.modelTrackContainer_)
 this.modelTrackContainer_.removeEventListener('scroll',this.onModelTrackControllerScroll_);this.modelTrackContainer_=m;this.modelTrackContainer_.addEventListener('scroll',this.onModelTrackControllerScroll_);},get showFlowEvents(){return this.showFlowEvents_;},set showFlowEvents(showFlowEvents){this.showFlowEvents_=showFlowEvents;this.dispatchChangeEvent();},get highlightVSync(){return this.highlightVSync_;},set highlightVSync(highlightVSync){this.highlightVSync_=highlightVSync;this.dispatchChangeEvent();},get highDetails(){return this.highDetails_;},set highDetails(highDetails){this.highDetails_=highDetails;this.dispatchChangeEvent();},get gridEnabled(){return this.gridEnabled_;},set gridEnabled(enabled){if(this.gridEnabled_==enabled)
 return;this.gridEnabled_=enabled&&true;this.dispatchChangeEvent();},get gridTimebase(){return this.gridTimebase_;},set gridTimebase(timebase){if(this.gridTimebase_==timebase)
-return;this.gridTimebase_=timebase;this.dispatchChangeEvent();},get gridStep(){return this.gridStep_;},get interestRange(){return this.interestRange_;},drawMajorMarkLines:function(ctx){ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();for(var idx in this.majorMarkPositions){var x=Math.floor(this.majorMarkPositions[idx]);tv.c.drawLine(ctx,x,0,x,ctx.canvas.height);}
+return;this.gridTimebase_=timebase;this.dispatchChangeEvent();},get gridStep(){return this.gridStep_;},get interestRange(){return this.interestRange_;},drawMajorMarkLines:function(ctx){ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();for(var idx in this.majorMarkPositions){var x=Math.floor(this.majorMarkPositions[idx]);tr.c.drawLine(ctx,x,0,x,ctx.canvas.height);}
 ctx.strokeStyle='#ddd';ctx.stroke();ctx.restore();},drawGridLines:function(ctx,viewLWorld,viewRWorld){if(!this.gridEnabled)
-return;var dt=this.currentDisplayTransform;var x=this.gridTimebase;ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();while(x<viewRWorld){if(x>=viewLWorld){var vx=Math.floor(dt.xWorldToView(x));tv.c.drawLine(ctx,vx,0,vx,ctx.canvas.height);}
+return;var dt=this.currentDisplayTransform;var x=this.gridTimebase;ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();while(x<viewRWorld){if(x>=viewLWorld){var vx=Math.floor(dt.xWorldToView(x));tr.c.drawLine(ctx,vx,0,vx,ctx.canvas.height);}
 x+=this.gridStep;}
 ctx.strokeStyle='rgba(255, 0, 0, 0.25)';ctx.stroke();ctx.restore();},rebuildEventToTrackMap:function(){this.eventToTrackMap_=undefined;var eventToTrackMap={};eventToTrackMap.addEvent=function(event,track){if(!track)
-throw new Error('Must provide a track.');this[event.guid]=track;};this.modelTrackContainer_.addEventsToTrackMap(eventToTrackMap);this.eventToTrackMap_=eventToTrackMap;},rebuildContainerToTrackMap:function(){this.containerToTrackObj.clearMap();this.modelTrackContainer_.addContainersToTrackMap(this.containerToTrackObj);},trackForEvent:function(event){return this.eventToTrackMap_[event.guid];}};return{ContainerToTrackObj:ContainerToTrackObj,TimelineViewport:TimelineViewport};});'use strict';tv.exportTo('tv.c',function(){var kDefaultPanAnimatoinDurationMs=100.0;function TimelineDisplayTransformPanAnimation(deltaX,deltaY,opt_durationMs){this.deltaX=deltaX;this.deltaY=deltaY;if(opt_durationMs===undefined)
+throw new Error('Must provide a track.');this[event.guid]=track;};this.modelTrackContainer_.addEventsToTrackMap(eventToTrackMap);this.eventToTrackMap_=eventToTrackMap;},rebuildContainerToTrackMap:function(){this.containerToTrackObj.clearMap();this.modelTrackContainer_.addContainersToTrackMap(this.containerToTrackObj);},trackForEvent:function(event){return this.eventToTrackMap_[event.guid];}};return{ContainerToTrackObj:ContainerToTrackObj,TimelineViewport:TimelineViewport};});'use strict';tr.exportTo('tr.c',function(){var kDefaultPanAnimatoinDurationMs=100.0;function TimelineDisplayTransformPanAnimation(deltaX,deltaY,opt_durationMs){this.deltaX=deltaX;this.deltaY=deltaY;if(opt_durationMs===undefined)
 this.durationMs=kDefaultPanAnimatoinDurationMs;else
 this.durationMs=opt_durationMs;this.startPanX=undefined;this.startPanY=undefined;this.startTimeMs=undefined;}
-TimelineDisplayTransformPanAnimation.prototype={__proto__:tv.b.ui.Animation.prototype,get affectsPanY(){return this.deltaY!==0;},canTakeOverFor:function(existingAnimation){return existingAnimation instanceof TimelineDisplayTransformPanAnimation;},takeOverFor:function(existing,timestamp,target){var remainingDeltaXOnExisting=existing.goalPanX-target.panX;var remainingDeltaYOnExisting=existing.goalPanY-target.panY;var remainingTimeOnExisting=timestamp-(existing.startTimeMs+existing.durationMs);remainingTimeOnExisting=Math.max(remainingTimeOnExisting,0);this.deltaX+=remainingDeltaXOnExisting;this.deltaY+=remainingDeltaYOnExisting;this.durationMs+=remainingTimeOnExisting;},start:function(timestamp,target){this.startTimeMs=timestamp;this.startPanX=target.panX;this.startPanY=target.panY;},tick:function(timestamp,target){var percentDone=(timestamp-this.startTimeMs)/this.durationMs;percentDone=tv.b.clamp(percentDone,0,1);target.panX=tv.b.lerp(percentDone,this.startPanX,this.goalPanX);if(this.affectsPanY)
-target.panY=tv.b.lerp(percentDone,this.startPanY,this.goalPanY);return timestamp>=this.startTimeMs+this.durationMs;},get goalPanX(){return this.startPanX+this.deltaX;},get goalPanY(){return this.startPanY+this.deltaY;}};function TimelineDisplayTransformZoomToAnimation(goalFocalPointXWorld,goalFocalPointXView,goalFocalPointY,zoomInRatioX,opt_durationMs){this.goalFocalPointXWorld=goalFocalPointXWorld;this.goalFocalPointXView=goalFocalPointXView;this.goalFocalPointY=goalFocalPointY;this.zoomInRatioX=zoomInRatioX;if(opt_durationMs===undefined)
+TimelineDisplayTransformPanAnimation.prototype={__proto__:tr.b.ui.Animation.prototype,get affectsPanY(){return this.deltaY!==0;},canTakeOverFor:function(existingAnimation){return existingAnimation instanceof TimelineDisplayTransformPanAnimation;},takeOverFor:function(existing,timestamp,target){var remainingDeltaXOnExisting=existing.goalPanX-target.panX;var remainingDeltaYOnExisting=existing.goalPanY-target.panY;var remainingTimeOnExisting=timestamp-(existing.startTimeMs+existing.durationMs);remainingTimeOnExisting=Math.max(remainingTimeOnExisting,0);this.deltaX+=remainingDeltaXOnExisting;this.deltaY+=remainingDeltaYOnExisting;this.durationMs+=remainingTimeOnExisting;},start:function(timestamp,target){this.startTimeMs=timestamp;this.startPanX=target.panX;this.startPanY=target.panY;},tick:function(timestamp,target){var percentDone=(timestamp-this.startTimeMs)/this.durationMs;percentDone=tr.b.clamp(percentDone,0,1);target.panX=tr.b.lerp(percentDone,this.startPanX,this.goalPanX);if(this.affectsPanY)
+target.panY=tr.b.lerp(percentDone,this.startPanY,this.goalPanY);return timestamp>=this.startTimeMs+this.durationMs;},get goalPanX(){return this.startPanX+this.deltaX;},get goalPanY(){return this.startPanY+this.deltaY;}};function TimelineDisplayTransformZoomToAnimation(goalFocalPointXWorld,goalFocalPointXView,goalFocalPointY,zoomInRatioX,opt_durationMs){this.goalFocalPointXWorld=goalFocalPointXWorld;this.goalFocalPointXView=goalFocalPointXView;this.goalFocalPointY=goalFocalPointY;this.zoomInRatioX=zoomInRatioX;if(opt_durationMs===undefined)
 this.durationMs=kDefaultPanAnimatoinDurationMs;else
 this.durationMs=opt_durationMs;this.startTimeMs=undefined;this.startScaleX=undefined;this.goalScaleX=undefined;this.startPanY=undefined;}
-TimelineDisplayTransformZoomToAnimation.prototype={__proto__:tv.b.ui.Animation.prototype,get affectsPanY(){return this.startPanY!=this.goalFocalPointY;},canTakeOverFor:function(existingAnimation){return false;},takeOverFor:function(existingAnimation,timestamp,target){this.goalScaleX=target.scaleX*this.zoomInRatioX;},start:function(timestamp,target){this.startTimeMs=timestamp;this.startScaleX=target.scaleX;this.goalScaleX=this.zoomInRatioX*target.scaleX;this.startPanY=target.panY;},tick:function(timestamp,target){var percentDone=(timestamp-this.startTimeMs)/this.durationMs;percentDone=tv.b.clamp(percentDone,0,1);target.scaleX=tv.b.lerp(percentDone,this.startScaleX,this.goalScaleX);if(this.affectsPanY){target.panY=tv.b.lerp(percentDone,this.startPanY,this.goalFocalPointY);}
-target.xPanWorldPosToViewPos(this.goalFocalPointXWorld,this.goalFocalPointXView);return timestamp>=this.startTimeMs+this.durationMs;}};return{TimelineDisplayTransformPanAnimation:TimelineDisplayTransformPanAnimation,TimelineDisplayTransformZoomToAnimation:TimelineDisplayTransformZoomToAnimation};});'use strict';tv.exportTo('tv.c',function(){var constants={HEADING_WIDTH:250};return{constants:constants};});'use strict';tv.exportTo('tv.c',function(){var constants=tv.c.constants;function TimingTool(viewport,targetElement){this.viewport_=viewport;this.onMouseMove_=this.onMouseMove_.bind(this);this.onDblClick_=this.onDblClick_.bind(this);this.targetElement_=targetElement;this.isMovingLeftEdge_=false;};TimingTool.prototype={onEnterTiming:function(e){this.targetElement_.addEventListener('mousemove',this.onMouseMove_);this.targetElement_.addEventListener('dblclick',this.onDblClick_);},onBeginTiming:function(e){if(!this.isTouchPointInsideTrackBounds_(e.clientX,e.clientY))
+TimelineDisplayTransformZoomToAnimation.prototype={__proto__:tr.b.ui.Animation.prototype,get affectsPanY(){return this.startPanY!=this.goalFocalPointY;},canTakeOverFor:function(existingAnimation){return false;},takeOverFor:function(existingAnimation,timestamp,target){this.goalScaleX=target.scaleX*this.zoomInRatioX;},start:function(timestamp,target){this.startTimeMs=timestamp;this.startScaleX=target.scaleX;this.goalScaleX=this.zoomInRatioX*target.scaleX;this.startPanY=target.panY;},tick:function(timestamp,target){var percentDone=(timestamp-this.startTimeMs)/this.durationMs;percentDone=tr.b.clamp(percentDone,0,1);target.scaleX=tr.b.lerp(percentDone,this.startScaleX,this.goalScaleX);if(this.affectsPanY){target.panY=tr.b.lerp(percentDone,this.startPanY,this.goalFocalPointY);}
+target.xPanWorldPosToViewPos(this.goalFocalPointXWorld,this.goalFocalPointXView);return timestamp>=this.startTimeMs+this.durationMs;}};return{TimelineDisplayTransformPanAnimation:TimelineDisplayTransformPanAnimation,TimelineDisplayTransformZoomToAnimation:TimelineDisplayTransformZoomToAnimation};});'use strict';tr.exportTo('tr.c',function(){var constants={HEADING_WIDTH:250};return{constants:constants};});'use strict';tr.exportTo('tr.c',function(){var constants=tr.c.constants;function TimingTool(viewport,targetElement){this.viewport_=viewport;this.onMouseMove_=this.onMouseMove_.bind(this);this.onDblClick_=this.onDblClick_.bind(this);this.targetElement_=targetElement;this.isMovingLeftEdge_=false;};TimingTool.prototype={onEnterTiming:function(e){this.targetElement_.addEventListener('mousemove',this.onMouseMove_);this.targetElement_.addEventListener('dblclick',this.onDblClick_);},onBeginTiming:function(e){if(!this.isTouchPointInsideTrackBounds_(e.clientX,e.clientY))
 return;var pt=this.getSnappedToEventPosition_(e);this.mouseDownAt_(pt.x,pt.y);this.updateSnapIndicators_(pt);},updateSnapIndicators_:function(pt){if(!pt.snapped)
 return;var ir=this.viewport_.interestRange;if(ir.min===pt.x)
-ir.leftSnapIndicator=new tv.c.SnapIndicator(pt.y,pt.height);if(ir.max===pt.x)
-ir.rightSnapIndicator=new tv.c.SnapIndicator(pt.y,pt.height);},onUpdateTiming:function(e){var pt=this.getSnappedToEventPosition_(e);this.mouseMoveAt_(pt.x,pt.y,true);this.updateSnapIndicators_(pt);},onEndTiming:function(e){this.mouseUp_();},onExitTiming:function(e){this.targetElement_.removeEventListener('mousemove',this.onMouseMove_);this.targetElement_.removeEventListener('dblclick',this.onDblClick_);},onMouseMove_:function(e){if(e.button)
+ir.leftSnapIndicator=new tr.c.SnapIndicator(pt.y,pt.height);if(ir.max===pt.x)
+ir.rightSnapIndicator=new tr.c.SnapIndicator(pt.y,pt.height);},onUpdateTiming:function(e){var pt=this.getSnappedToEventPosition_(e);this.mouseMoveAt_(pt.x,pt.y,true);this.updateSnapIndicators_(pt);},onEndTiming:function(e){this.mouseUp_();},onExitTiming:function(e){this.targetElement_.removeEventListener('mousemove',this.onMouseMove_);this.targetElement_.removeEventListener('dblclick',this.onDblClick_);},onMouseMove_:function(e){if(e.button)
 return;var worldX=this.getWorldXFromEvent_(e);this.mouseMoveAt_(worldX,e.clientY,false);},onDblClick_:function(e){console.error('not implemented');},isTouchPointInsideTrackBounds_:function(clientX,clientY){if(!this.viewport_||!this.viewport_.modelTrackContainer||!this.viewport_.modelTrackContainer.canvas)
 return false;var canvas=this.viewport_.modelTrackContainer.canvas;var canvasRect=canvas.getBoundingClientRect();if(clientX>=canvasRect.left&&clientX<=canvasRect.right&&clientY>=canvasRect.top&&clientY<=canvasRect.bottom)
 return true;return false;},mouseDownAt_:function(worldX,y){var ir=this.viewport_.interestRange;var dt=this.viewport_.currentDisplayTransform;var pixelRatio=window.devicePixelRatio||1;var nearnessThresholdWorld=dt.xViewVectorToWorld(6*pixelRatio);if(ir.isEmpty){ir.setMinAndMax(worldX,worldX);ir.rightSelected=true;this.isMovingLeftEdge_=false;return;}
@@ -3149,83 +3220,72 @@
 b=newWorldX;if(a<=b)
 ir.setMinAndMax(a,b);else
 ir.setMinAndMax(b,a);if(ir.min==newWorldX){this.isMovingLeftEdge_=true;ir.leftSelected=true;ir.rightSelected=false;}else{this.isMovingLeftEdge_=false;ir.leftSelected=false;ir.rightSelected=true;}},mouseUp_:function(){var dt=this.viewport_.currentDisplayTransform;var ir=this.viewport_.interestRange;ir.leftSelected=false;ir.rightSelected=false;var pixelRatio=window.devicePixelRatio||1;var minWidthValue=dt.xViewVectorToWorld(2*pixelRatio);if(ir.range<minWidthValue)
-ir.reset();},getWorldXFromEvent_:function(e){var pixelRatio=window.devicePixelRatio||1;var canvas=this.viewport_.modelTrackContainer.canvas;var worldOffset=canvas.getBoundingClientRect().left;var viewX=(e.clientX-worldOffset)*pixelRatio;return this.viewport_.currentDisplayTransform.xViewToWorld(viewX);},getSnappedToEventPosition_:function(e){var pixelRatio=window.devicePixelRatio||1;var EVENT_SNAP_RANGE=16*pixelRatio;var modelTrackContainer=this.viewport_.modelTrackContainer;var modelTrackContainerRect=modelTrackContainer.getBoundingClientRect();var viewport=this.viewport_;var dt=viewport.currentDisplayTransform;var worldMaxDist=dt.xViewVectorToWorld(EVENT_SNAP_RANGE);var worldX=this.getWorldXFromEvent_(e);var mouseY=e.clientY;var selection=new tv.c.Selection();modelTrackContainer.addClosestEventToSelection(worldX,worldMaxDist,mouseY,mouseY,selection);if(!selection.length){modelTrackContainer.addClosestEventToSelection(worldX,worldMaxDist,modelTrackContainerRect.top,modelTrackContainerRect.bottom,selection);}
-var minDistX=worldMaxDist;var minDistY=Infinity;var pixWidth=dt.xViewVectorToWorld(1);var result={x:worldX,y:mouseY-modelTrackContainerRect.top,height:0,snapped:false};var eventBounds=new tv.b.Range();for(var i=0;i<selection.length;i++){var event=selection[i];var track=viewport.trackForEvent(event);var trackRect=track.getBoundingClientRect();eventBounds.reset();event.addBoundsToRange(eventBounds);var eventX;if(Math.abs(eventBounds.min-worldX)<Math.abs(eventBounds.max-worldX)){eventX=eventBounds.min;}else{eventX=eventBounds.max;}
+ir.reset();},getWorldXFromEvent_:function(e){var pixelRatio=window.devicePixelRatio||1;var canvas=this.viewport_.modelTrackContainer.canvas;var worldOffset=canvas.getBoundingClientRect().left;var viewX=(e.clientX-worldOffset)*pixelRatio;return this.viewport_.currentDisplayTransform.xViewToWorld(viewX);},getSnappedToEventPosition_:function(e){var pixelRatio=window.devicePixelRatio||1;var EVENT_SNAP_RANGE=16*pixelRatio;var modelTrackContainer=this.viewport_.modelTrackContainer;var modelTrackContainerRect=modelTrackContainer.getBoundingClientRect();var viewport=this.viewport_;var dt=viewport.currentDisplayTransform;var worldMaxDist=dt.xViewVectorToWorld(EVENT_SNAP_RANGE);var worldX=this.getWorldXFromEvent_(e);var mouseY=e.clientY;var selection=new tr.c.Selection();modelTrackContainer.addClosestEventToSelection(worldX,worldMaxDist,mouseY,mouseY,selection);if(!selection.length){modelTrackContainer.addClosestEventToSelection(worldX,worldMaxDist,modelTrackContainerRect.top,modelTrackContainerRect.bottom,selection);}
+var minDistX=worldMaxDist;var minDistY=Infinity;var pixWidth=dt.xViewVectorToWorld(1);var result={x:worldX,y:mouseY-modelTrackContainerRect.top,height:0,snapped:false};var eventBounds=new tr.b.Range();for(var i=0;i<selection.length;i++){var event=selection[i];var track=viewport.trackForEvent(event);var trackRect=track.getBoundingClientRect();eventBounds.reset();event.addBoundsToRange(eventBounds);var eventX;if(Math.abs(eventBounds.min-worldX)<Math.abs(eventBounds.max-worldX)){eventX=eventBounds.min;}else{eventX=eventBounds.max;}
 var distX=eventX-worldX;var eventY=trackRect.top;var eventHeight=trackRect.height;var distY=Math.abs(eventY+eventHeight/2-mouseY);if((distX<=minDistX||Math.abs(distX-minDistX)<pixWidth)&&distY<minDistY){minDistX=distX;minDistY=distY;result.x=eventX;result.y=eventY+
 modelTrackContainer.scrollTop-modelTrackContainerRect.top;result.height=eventHeight;result.snapped=true;}}
-return result;}};return{TimingTool:TimingTool};});'use strict';tv.exportTo('tv.c.trace_model',function(){function Annotation(){this.guid_=tv.b.GUID.allocate();this.view_=undefined;};Annotation.fromDictIfPossible=function(args){if(args.typeName===undefined)
-throw new Error('Missing typeName argument');var typeInfo=Annotation.findTypeInfoMatching(function(typeInfo){return typeInfo.metadata.typeName===args.typeName;});if(typeInfo===undefined)
-return undefined;return typeInfo.constructor.fromDict(args);};Annotation.fromDict=function(){throw new Error('Not implemented');}
-Annotation.prototype={get guid(){return this.guid_;},onRemove:function(){},toDict:function(){throw new Error('Not implemented');},getOrCreateView:function(viewport){if(!this.view_)
-this.view_=this.createView_(viewport);return this.view_;},createView_:function(){throw new Error('Not implemented');}};var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);options.mandatoryBaseType=Annotation;tv.b.decorateExtensionRegistry(Annotation,options);Annotation.addEventListener('will-register',function(e){if(!e.typeInfo.constructor.hasOwnProperty('fromDict'))
-throw new Error('Must have fromDict method');if(!e.typeInfo.metadata.typeName)
-throw new Error('Registered Annotations must provide typeName');});return{Annotation:Annotation};});'use strict';tv.exportTo('tv.c.annotations',function(){function AnnotationView(viewport,annotation){}
-AnnotationView.prototype={draw:function(ctx){throw new Error('Not implemented');}};return{AnnotationView:AnnotationView};});'use strict';tv.exportTo('tv.c.annotations',function(){function XMarkerAnnotationView(viewport,annotation){this.viewport_=viewport;this.annotation_=annotation;}
-XMarkerAnnotationView.prototype={__proto__:tv.c.annotations.AnnotationView.prototype,draw:function(ctx){var dt=this.viewport_.currentDisplayTransform;var viewX=dt.xWorldToView(this.annotation_.timestamp);ctx.beginPath();tv.c.drawLine(ctx,viewX,0,viewX,ctx.canvas.height);ctx.strokeStyle=this.annotation_.strokeStyle;ctx.stroke();}};return{XMarkerAnnotationView:XMarkerAnnotationView};});'use strict';tv.exportTo('tv.c.trace_model',function(){function XMarkerAnnotation(timestamp){tv.c.trace_model.Annotation.apply(this,arguments);this.timestamp=timestamp;this.strokeStyle='rgba(0, 0, 255, 0.5)';}
-XMarkerAnnotation.fromDict=function(dict){return new XMarkerAnnotation(dict.args.timestamp);}
-XMarkerAnnotation.prototype={__proto__:tv.c.trace_model.Annotation.prototype,toDict:function(){return{typeName:'xmarker',args:{timestamp:this.timestamp}};},createView_:function(viewport){return new tv.c.annotations.XMarkerAnnotationView(viewport,this);}};tv.c.trace_model.Annotation.register(XMarkerAnnotation,{typeName:'xmarker'});return{XMarkerAnnotation:XMarkerAnnotation};});'use strict';tv.exportTo('tv.b.ui',function(){var ContainerThatDecoratesItsChildren=tv.b.ui.define('div');ContainerThatDecoratesItsChildren.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.observer_=new WebKitMutationObserver(this.didMutate_.bind(this));this.observer_.observe(this,{childList:true});Object.defineProperty(this,'textContent',{get:undefined,set:this.onSetTextContent_});},appendChild:function(x){HTMLUnknownElement.prototype.appendChild.call(this,x);this.didMutate_(this.observer_.takeRecords());},insertBefore:function(x,y){HTMLUnknownElement.prototype.insertBefore.call(this,x,y);this.didMutate_(this.observer_.takeRecords());},removeChild:function(x){HTMLUnknownElement.prototype.removeChild.call(this,x);this.didMutate_(this.observer_.takeRecords());},replaceChild:function(x,y){HTMLUnknownElement.prototype.replaceChild.call(this,x,y);this.didMutate_(this.observer_.takeRecords());},onSetTextContent_:function(textContent){if(textContent!='')
+return result;}};return{TimingTool:TimingTool};});'use strict';tr.exportTo('tr.b.ui',function(){var ContainerThatDecoratesItsChildren=tr.b.ui.define('div');ContainerThatDecoratesItsChildren.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.observer_=new WebKitMutationObserver(this.didMutate_.bind(this));this.observer_.observe(this,{childList:true});Object.defineProperty(this,'textContent',{get:undefined,set:this.onSetTextContent_});},appendChild:function(x){HTMLUnknownElement.prototype.appendChild.call(this,x);this.didMutate_(this.observer_.takeRecords());},insertBefore:function(x,y){HTMLUnknownElement.prototype.insertBefore.call(this,x,y);this.didMutate_(this.observer_.takeRecords());},removeChild:function(x){HTMLUnknownElement.prototype.removeChild.call(this,x);this.didMutate_(this.observer_.takeRecords());},replaceChild:function(x,y){HTMLUnknownElement.prototype.replaceChild.call(this,x,y);this.didMutate_(this.observer_.takeRecords());},onSetTextContent_:function(textContent){if(textContent!='')
 throw new Error('textContent can only be set to \'\'.');this.clear();},clear:function(){while(this.lastChild)
 HTMLUnknownElement.prototype.removeChild.call(this,this.lastChild);this.didMutate_(this.observer_.takeRecords());},didMutate_:function(records){this.beginDecorating_();for(var i=0;i<records.length;i++){var addedNodes=records[i].addedNodes;if(addedNodes){for(var j=0;j<addedNodes.length;j++)
 this.decorateChild_(addedNodes[j]);}
 var removedNodes=records[i].removedNodes;if(removedNodes){for(var j=0;j<removedNodes.length;j++){this.undecorateChild_(removedNodes[j]);}}}
-this.doneDecoratingForNow_();},decorateChild_:function(child){throw new Error('Not implemented');},undecorateChild_:function(child){throw new Error('Not implemented');},beginDecorating_:function(){},doneDecoratingForNow_:function(){}};return{ContainerThatDecoratesItsChildren:ContainerThatDecoratesItsChildren};});'use strict';tv.exportTo('tv.c.tracks',function(){var Track=tv.b.ui.define('track',tv.b.ui.ContainerThatDecoratesItsChildren);Track.prototype={__proto__:tv.b.ui.ContainerThatDecoratesItsChildren.prototype,decorate:function(viewport){tv.b.ui.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);if(viewport===undefined)
-throw new Error('viewport is required when creating a Track.');this.viewport_=viewport;this.classList.add('track');},get viewport(){return this.viewport_;},get drawingContainer(){var cur=this;while(cur){if(cur instanceof tv.c.tracks.DrawingContainer)
+this.doneDecoratingForNow_();},decorateChild_:function(child){throw new Error('Not implemented');},undecorateChild_:function(child){throw new Error('Not implemented');},beginDecorating_:function(){},doneDecoratingForNow_:function(){}};return{ContainerThatDecoratesItsChildren:ContainerThatDecoratesItsChildren};});'use strict';tr.exportTo('tr.c.tracks',function(){var Track=tr.b.ui.define('track',tr.b.ui.ContainerThatDecoratesItsChildren);Track.prototype={__proto__:tr.b.ui.ContainerThatDecoratesItsChildren.prototype,decorate:function(viewport){tr.b.ui.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);if(viewport===undefined)
+throw new Error('viewport is required when creating a Track.');this.viewport_=viewport;this.classList.add('track');},get viewport(){return this.viewport_;},get drawingContainer(){var cur=this;while(cur){if(cur instanceof tr.c.tracks.DrawingContainer)
 return cur;cur=cur.parentElement;}
 return undefined;},get eventContainer(){},invalidateDrawingContainer:function(){var dc=this.drawingContainer;if(dc)
 dc.invalidate();},context:function(){if(!this.parentNode)
 return undefined;if(!this.parentNode.context)
 throw new Error('Parent container does not support context() method.');return this.parentNode.context();},decorateChild_:function(childTrack){},undecorateChild_:function(childTrack){if(childTrack.detach)
 childTrack.detach();},updateContents_:function(){},drawTrack:function(type){var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));var dt=this.viewport.currentDisplayTransform;var viewLWorld=dt.xViewToWorld(0);var viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);this.draw(type,viewLWorld,viewRWorld);ctx.restore();},draw:function(type,viewLWorld,viewRWorld){},addEventsToTrackMap:function(eventToTrackMap){},addContainersToTrackMap:function(containerToTrackMap){},addIntersectingEventsInRangeToSelection:function(loVX,hiVX,loVY,hiVY,selection){var pixelRatio=window.devicePixelRatio||1;var dt=this.viewport.currentDisplayTransform;var viewPixWidthWorld=dt.xViewVectorToWorld(1);var loWX=dt.xViewToWorld(loVX*pixelRatio);var hiWX=dt.xViewToWorld(hiVX*pixelRatio);var clientRect=this.getBoundingClientRect();var a=Math.max(loVY,clientRect.top);var b=Math.min(hiVY,clientRect.bottom);if(a>b)
-return;this.addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection);},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){},addClosestInstantEventToSelection:function(instantEvents,worldX,worldMaxDist,selection){var instantEvent=tv.b.findClosestElementInSortedArray(instantEvents,function(x){return x.start;},worldX,worldMaxDist);if(!instantEvent)
-return;selection.push(instantEvent);}};return{Track:Track};});'use strict';tv.exportTo('tv.c.tracks',function(){var DrawType={GENERAL_EVENT:1,INSTANT_EVENT:2,BACKGROUND:3,GRID:4,FLOW_ARROWS:5,MARKERS:6,HIGHLIGHTS:7,ANNOTATIONS:8};var DrawingContainer=tv.b.ui.define('drawing-container',tv.c.tracks.Track);DrawingContainer.prototype={__proto__:tv.c.tracks.Track.prototype,decorate:function(viewport){tv.c.tracks.Track.prototype.decorate.call(this,viewport);this.classList.add('drawing-container');this.canvas_=document.createElement('canvas');this.canvas_.className='drawing-container-canvas';this.canvas_.style.left=tv.c.constants.HEADING_WIDTH+'px';this.appendChild(this.canvas_);this.ctx_=this.canvas_.getContext('2d');this.viewportChange_=this.viewportChange_.bind(this);this.viewport.addEventListener('change',this.viewportChange_);},get canvas(){return this.canvas_;},context:function(){return this.ctx_;},viewportChange_:function(){this.invalidate();},invalidate:function(){if(this.rafPending_)
-return;this.rafPending_=true;tv.b.requestPreAnimationFrame(this.preDraw_,this);},preDraw_:function(){this.rafPending_=false;this.updateCanvasSizeIfNeeded_();tv.b.requestAnimationFrameInThisFrameIfPossible(this.draw_,this);},draw_:function(){this.ctx_.clearRect(0,0,this.canvas_.width,this.canvas_.height);var typesToDraw=[DrawType.BACKGROUND,DrawType.HIGHLIGHTS,DrawType.GRID,DrawType.INSTANT_EVENT,DrawType.GENERAL_EVENT,DrawType.MARKERS,DrawType.ANNOTATIONS];if(this.viewport.showFlowEvents)
-typesToDraw.push(DrawType.FLOW_ARROWS);for(var idx in typesToDraw){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tv.c.tracks.Track))
+return;this.addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection);},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){},addClosestInstantEventToSelection:function(instantEvents,worldX,worldMaxDist,selection){var instantEvent=tr.b.findClosestElementInSortedArray(instantEvents,function(x){return x.start;},worldX,worldMaxDist);if(!instantEvent)
+return;selection.push(instantEvent);}};return{Track:Track};});'use strict';tr.exportTo('tr.c.tracks',function(){var DrawType={GENERAL_EVENT:1,INSTANT_EVENT:2,BACKGROUND:3,GRID:4,FLOW_ARROWS:5,MARKERS:6,HIGHLIGHTS:7,ANNOTATIONS:8};var DrawingContainer=tr.b.ui.define('drawing-container',tr.c.tracks.Track);DrawingContainer.prototype={__proto__:tr.c.tracks.Track.prototype,decorate:function(viewport){tr.c.tracks.Track.prototype.decorate.call(this,viewport);this.classList.add('drawing-container');this.canvas_=document.createElement('canvas');this.canvas_.className='drawing-container-canvas';this.canvas_.style.left=tr.c.constants.HEADING_WIDTH+'px';this.appendChild(this.canvas_);this.ctx_=this.canvas_.getContext('2d');this.viewportChange_=this.viewportChange_.bind(this);this.viewport.addEventListener('change',this.viewportChange_);},get canvas(){return this.canvas_;},context:function(){return this.ctx_;},viewportChange_:function(){this.invalidate();},invalidate:function(){if(this.rafPending_)
+return;this.rafPending_=true;tr.b.requestPreAnimationFrame(this.preDraw_,this);},preDraw_:function(){this.rafPending_=false;this.updateCanvasSizeIfNeeded_();tr.b.requestAnimationFrameInThisFrameIfPossible(this.draw_,this);},draw_:function(){this.ctx_.clearRect(0,0,this.canvas_.width,this.canvas_.height);var typesToDraw=[DrawType.BACKGROUND,DrawType.HIGHLIGHTS,DrawType.GRID,DrawType.INSTANT_EVENT,DrawType.GENERAL_EVENT,DrawType.MARKERS,DrawType.ANNOTATIONS,DrawType.FLOW_ARROWS];for(var idx in typesToDraw){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.c.tracks.Track))
 continue;this.children[i].drawTrack(typesToDraw[idx]);}}
-var pixelRatio=window.devicePixelRatio||1;var bounds=this.canvas_.getBoundingClientRect();var dt=this.viewport.currentDisplayTransform;var viewLWorld=dt.xViewToWorld(0);var viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);this.viewport.drawGridLines(this.ctx_,viewLWorld,viewRWorld);},updateCanvasSizeIfNeeded_:function(){var visibleChildTracks=tv.b.asArray(this.children).filter(this.visibleFilter_);var thisBounds=this.getBoundingClientRect();var firstChildTrackBounds=visibleChildTracks[0].getBoundingClientRect();var lastChildTrackBounds=visibleChildTracks[visibleChildTracks.length-1].getBoundingClientRect();var innerWidth=firstChildTrackBounds.width-
-tv.c.constants.HEADING_WIDTH;var innerHeight=lastChildTrackBounds.bottom-firstChildTrackBounds.top;var pixelRatio=window.devicePixelRatio||1;if(this.canvas_.width!=innerWidth*pixelRatio){this.canvas_.width=innerWidth*pixelRatio;this.canvas_.style.width=innerWidth+'px';}
-if(this.canvas_.height!=innerHeight*pixelRatio){this.canvas_.height=innerHeight*pixelRatio;this.canvas_.style.height=innerHeight+'px';}},visibleFilter_:function(element){if(!(element instanceof tv.c.tracks.Track))
-return false;return window.getComputedStyle(element).display!=='none';},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tv.c.tracks.Track))
+var pixelRatio=window.devicePixelRatio||1;var bounds=this.canvas_.getBoundingClientRect();var dt=this.viewport.currentDisplayTransform;var viewLWorld=dt.xViewToWorld(0);var viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);this.viewport.drawGridLines(this.ctx_,viewLWorld,viewRWorld);},updateCanvasSizeIfNeeded_:function(){var visibleChildTracks=tr.b.asArray(this.children).filter(this.visibleFilter_);var thisBounds=this.getBoundingClientRect();var firstChildTrackBounds=visibleChildTracks[0].getBoundingClientRect();var lastChildTrackBounds=visibleChildTracks[visibleChildTracks.length-1].getBoundingClientRect();var innerWidth=firstChildTrackBounds.width-
+tr.c.constants.HEADING_WIDTH;var innerHeight=lastChildTrackBounds.bottom-firstChildTrackBounds.top;var pixelRatio=window.devicePixelRatio||1;if(this.canvas_.width!=innerWidth*pixelRatio){this.canvas_.width=innerWidth*pixelRatio;this.canvas_.style.width=innerWidth+'px';}
+if(this.canvas_.height!=innerHeight*pixelRatio){this.canvas_.height=innerHeight*pixelRatio;this.canvas_.style.height=innerHeight+'px';}},visibleFilter_:function(element){if(!(element instanceof tr.c.tracks.Track))
+return false;return window.getComputedStyle(element).display!=='none';},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.c.tracks.Track))
 continue;var trackClientRect=this.children[i].getBoundingClientRect();var a=Math.max(loY,trackClientRect.top);var b=Math.min(hiY,trackClientRect.bottom);if(a<=b){this.children[i].addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);}}
-tv.c.tracks.Track.prototype.addClosestEventToSelection.apply(this,arguments);},addEventsToTrackMap:function(eventToTrackMap){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tv.c.tracks.Track))
-continue;this.children[i].addEventsToTrackMap(eventToTrackMap);}},addContainersToTrackMap:function(containerToTrackMap){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tv.c.tracks.Track))
-continue;this.children[i].addContainersToTrackMap(containerToTrackMap);}}};return{DrawingContainer:DrawingContainer,DrawType:DrawType};});'use strict';tv.exportTo('tv.c.tracks',function(){function Highlighter(viewport){if(viewport===undefined){throw new Error('viewport must be provided');}
-this.viewport_=viewport;};Highlighter.prototype={__proto__:Object.prototype,processModel:function(model){throw new Error('processModel implementation missing');},drawHighlight:function(ctx,dt,viewLWorld,viewRWorld,viewHeight){throw new Error('drawHighlight implementation missing');}};var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Highlighter;tv.b.decorateExtensionRegistry(Highlighter,options);return{Highlighter:Highlighter};});'use strict';tv.exportTo('tv.c.tracks',function(){var Task=tv.b.Task;var ContainerTrack=tv.b.ui.define('container-track',tv.c.tracks.Track);ContainerTrack.prototype={__proto__:tv.c.tracks.Track.prototype,decorate:function(viewport){tv.c.tracks.Track.prototype.decorate.call(this,viewport);},detach:function(){this.textContent='';},get tracks_(){var tracks=[];for(var i=0;i<this.children.length;i++){if(this.children[i].classList.contains('track'))
+tr.c.tracks.Track.prototype.addClosestEventToSelection.apply(this,arguments);},addEventsToTrackMap:function(eventToTrackMap){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.c.tracks.Track))
+continue;this.children[i].addEventsToTrackMap(eventToTrackMap);}},addContainersToTrackMap:function(containerToTrackMap){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.c.tracks.Track))
+continue;this.children[i].addContainersToTrackMap(containerToTrackMap);}}};return{DrawingContainer:DrawingContainer,DrawType:DrawType};});'use strict';tr.exportTo('tr.c.tracks',function(){function Highlighter(viewport){if(viewport===undefined){throw new Error('viewport must be provided');}
+this.viewport_=viewport;};Highlighter.prototype={__proto__:Object.prototype,processModel:function(model){throw new Error('processModel implementation missing');},drawHighlight:function(ctx,dt,viewLWorld,viewRWorld,viewHeight){throw new Error('drawHighlight implementation missing');}};var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Highlighter;tr.b.decorateExtensionRegistry(Highlighter,options);return{Highlighter:Highlighter};});'use strict';tr.exportTo('tr.c.tracks',function(){var Task=tr.b.Task;var ContainerTrack=tr.b.ui.define('container-track',tr.c.tracks.Track);ContainerTrack.prototype={__proto__:tr.c.tracks.Track.prototype,decorate:function(viewport){tr.c.tracks.Track.prototype.decorate.call(this,viewport);},detach:function(){this.textContent='';},get tracks_(){var tracks=[];for(var i=0;i<this.children.length;i++){if(this.children[i].classList.contains('track'))
 tracks.push(this.children[i]);}
-return tracks;},drawTrack:function(type){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tv.c.tracks.Track))
+return tracks;},drawTrack:function(type){for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.c.tracks.Track))
 continue;this.children[i].drawTrack(type);}},addIntersectingEventsInRangeToSelection:function(loVX,hiVX,loY,hiY,selection){for(var i=0;i<this.tracks_.length;i++){var trackClientRect=this.tracks_[i].getBoundingClientRect();var a=Math.max(loY,trackClientRect.top);var b=Math.min(hiY,trackClientRect.bottom);if(a<=b)
 this.tracks_[i].addIntersectingEventsInRangeToSelection(loVX,hiVX,loY,hiY,selection);}
-tv.c.tracks.Track.prototype.addIntersectingEventsInRangeToSelection.apply(this,arguments);},addEventsToTrackMap:function(eventToTrackMap){for(var i=0;i<this.children.length;++i)
+tr.c.tracks.Track.prototype.addIntersectingEventsInRangeToSelection.apply(this,arguments);},addEventsToTrackMap:function(eventToTrackMap){for(var i=0;i<this.children.length;++i)
 this.children[i].addEventsToTrackMap(eventToTrackMap);},addAllEventsMatchingFilterToSelection:function(filter,selection){for(var i=0;i<this.tracks_.length;i++)
 this.tracks_[i].addAllEventsMatchingFilterToSelection(filter,selection);},addAllEventsMatchingFilterToSelectionAsTask:function(filter,selection){var task=new Task();for(var i=0;i<this.tracks_.length;i++){task.subTask(function(i){return function(){this.tracks_[i].addAllEventsMatchingFilterToSelection(filter,selection);}}(i),this);}
 return task;},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){for(var i=0;i<this.tracks_.length;i++){var trackClientRect=this.tracks_[i].getBoundingClientRect();var a=Math.max(loY,trackClientRect.top);var b=Math.min(hiY,trackClientRect.bottom);if(a<=b){this.tracks_[i].addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);}}
-tv.c.tracks.Track.prototype.addClosestEventToSelection.apply(this,arguments);}};return{ContainerTrack:ContainerTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){function ChartAxis(opt_min,opt_max){this.guid_=tv.b.GUID.allocate();this.bounds=new tv.b.Range();if(opt_min!==undefined)
+tr.c.tracks.Track.prototype.addClosestEventToSelection.apply(this,arguments);}};return{ContainerTrack:ContainerTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){function ChartAxis(opt_min,opt_max){this.guid_=tr.b.GUID.allocate();this.bounds=new tr.b.Range();if(opt_min!==undefined)
 this.bounds.addValue(opt_min);if(opt_max!==undefined)
 this.bounds.addValue(opt_max);};ChartAxis.prototype={get guid(){return this.guid_;},valueToUnitRange:function(value){if(this.bounds.isEmpty)
 throw new Error('Chart axis bounds are empty');var bounds=this.bounds;if(bounds.range===0)
-return 0;return(value-bounds.min)/bounds.range;},autoSetFromSeries:function(series,opt_config){var range=new tv.b.Range();series.forEach(function(s){range.addRange(s.range);},this);this.autoSetFromRange(range,opt_config);},autoSetFromRange:function(range,opt_config){if(range.isEmpty)
+return 0;return(value-bounds.min)/bounds.range;},autoSetFromSeries:function(series,opt_config){var range=new tr.b.Range();series.forEach(function(s){range.addRange(s.range);},this);this.autoSetFromRange(range,opt_config);},autoSetFromRange:function(range,opt_config){if(range.isEmpty)
 return;var bounds=this.bounds;if(bounds.isEmpty){bounds.addRange(range);return;}
 if(!opt_config)
 return;var useRangeMin=(opt_config.expandMin&&range.min<bounds.min||opt_config.shrinkMin&&range.min>bounds.min);var useRangeMax=(opt_config.expandMax&&range.max>bounds.max||opt_config.shrinkMax&&range.max<bounds.max);if(!useRangeMin&&!useRangeMax)
 return;if(useRangeMin&&useRangeMax){bounds.min=range.min;bounds.max=range.max;return;}
-if(useRangeMin){bounds.min=Math.min(range.min,bounds.max);}else{bounds.max=Math.max(range.max,bounds.min);}}};return{ChartAxis:ChartAxis};});'use strict';tv.exportTo('tv.c.trace_model',function(){var SelectableItem=tv.c.trace_model.SelectableItem;var SelectionState=tv.c.trace_model.SelectionState;function ProxySelectableItem(modelItem){SelectableItem.call(this,modelItem);};ProxySelectableItem.prototype={__proto__:SelectableItem.prototype,get selectionState(){var modelItem=this.modelItem_;if(modelItem===undefined)
-return SelectionState.NONE;return modelItem.selectionState;}};return{ProxySelectableItem:ProxySelectableItem};});'use strict';tv.exportTo('tv.c.tracks',function(){function ChartPoint(modelItem,x,y,opt_yBase){tv.c.trace_model.ProxySelectableItem.call(this,modelItem);this.x=x;this.y=y;this.yBase=opt_yBase;};ChartPoint.prototype={__proto__:tv.c.trace_model.ProxySelectableItem.prototype};return{ChartPoint:ChartPoint};});'use strict';tv.exportTo('tv.c.tracks',function(){var DOWN_ARROW=String.fromCharCode(0x25BE);var RIGHT_ARROW=String.fromCharCode(0x25B8);var HeadingTrack=tv.b.ui.define('heading-track',tv.c.tracks.Track);HeadingTrack.prototype={__proto__:tv.c.tracks.Track.prototype,decorate:function(viewport){tv.c.tracks.Track.prototype.decorate.call(this,viewport);this.classList.add('heading-track');this.headingDiv_=document.createElement('heading');this.headingDiv_.style.width=tv.c.constants.HEADING_WIDTH+'px';this.headingDiv_.addEventListener('click',this.onHeadingDivClicked_.bind(this));this.heading_='';this.expanded_=undefined;this.selectionGenerator_=undefined;this.updateContents_();},get heading(){return this.heading_;},set heading(text){this.heading_=text;this.updateContents_();},set tooltip(text){this.headingDiv_.title=text;},set selectionGenerator(generator){this.selectionGenerator_=generator;this.updateContents_();},get expanded(){return this.expanded_;},set expanded(expanded){expanded=expanded;if(this.expanded_==expanded)
-return;this.expanded_=expanded;this.expandedStateChanged_();},expandedStateChanged_:function(){this.updateHeadigDiv_();},onHeadingDivClicked_:function(){var e=new Event('heading-clicked',true,false);this.dispatchEvent(e);},updateContents_:function(){this.updateHeadigDiv_();},updateHeadigDiv_:function(){this.headingDiv_.innerHTML='';var span=document.createElement('span');span.classList.add('heading-arrow');if(this.expanded===true)
+if(useRangeMin){bounds.min=Math.min(range.min,bounds.max);}else{bounds.max=Math.max(range.max,bounds.min);}}};return{ChartAxis:ChartAxis};});'use strict';tr.exportTo('tr.model',function(){var SelectableItem=tr.model.SelectableItem;var SelectionState=tr.model.SelectionState;function ProxySelectableItem(modelItem){SelectableItem.call(this,modelItem);};ProxySelectableItem.prototype={__proto__:SelectableItem.prototype,get selectionState(){var modelItem=this.modelItem_;if(modelItem===undefined)
+return SelectionState.NONE;return modelItem.selectionState;}};return{ProxySelectableItem:ProxySelectableItem};});'use strict';tr.exportTo('tr.c.tracks',function(){function ChartPoint(modelItem,x,y,opt_yBase){tr.model.ProxySelectableItem.call(this,modelItem);this.x=x;this.y=y;this.yBase=opt_yBase;};ChartPoint.prototype={__proto__:tr.model.ProxySelectableItem.prototype};return{ChartPoint:ChartPoint};});'use strict';tr.exportTo('tr.c.tracks',function(){var DOWN_ARROW=String.fromCharCode(0x25BE);var RIGHT_ARROW=String.fromCharCode(0x25B8);var HeadingTrack=tr.b.ui.define('heading-track',tr.c.tracks.Track);HeadingTrack.prototype={__proto__:tr.c.tracks.Track.prototype,decorate:function(viewport){tr.c.tracks.Track.prototype.decorate.call(this,viewport);this.classList.add('heading-track');this.headingDiv_=document.createElement('heading');this.headingDiv_.style.width=tr.c.constants.HEADING_WIDTH+'px';this.headingDiv_.addEventListener('click',this.onHeadingDivClicked_.bind(this));this.heading_='';this.expanded_=undefined;this.selectionGenerator_=undefined;this.updateContents_();},get heading(){return this.heading_;},set heading(text){this.heading_=text;this.updateContents_();},set tooltip(text){this.headingDiv_.title=text;},set selectionGenerator(generator){this.selectionGenerator_=generator;this.updateContents_();},get expanded(){return this.expanded_;},set expanded(expanded){expanded=expanded;if(this.expanded_==expanded)
+return;this.expanded_=expanded;this.expandedStateChanged_();},expandedStateChanged_:function(){this.updateHeadigDiv_();},onHeadingDivClicked_:function(){var e=new Event('heading-clicked',{'bubbles':true});this.dispatchEvent(e);},updateContents_:function(){this.updateHeadigDiv_();},updateHeadigDiv_:function(){this.headingDiv_.innerHTML='';var span=document.createElement('span');span.classList.add('heading-arrow');if(this.expanded===true)
 span.textContent=DOWN_ARROW;else if(this.expanded===false)
 span.textContent=RIGHT_ARROW;else
-span.textContent='';this.headingDiv_.appendChild(span);if(this.selectionGenerator_){this.headingLink_=document.createElement('tv-c-analysis-link');this.headingLink_.selection=this.selectionGenerator_;this.headingLink_.textContent='';this.headingDiv_.appendChild(this.headingLink_);this.headingLink_.appendChild(document.createTextNode(this.heading_));}else{span=document.createElement('span');span.textContent=this.heading_;this.headingDiv_.appendChild(span);}
-this.appendChild(this.headingDiv_);},draw:function(type,viewLWorld,viewRWorld){throw new Error('draw implementation missing');}};return{HeadingTrack:HeadingTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var EventPresenter=tv.c.EventPresenter;var SelectionState=tv.c.trace_model.SelectionState;var ChartSeriesType={LINE:0,AREA:1};var DEFAULT_RENDERING_CONFIG={chartType:ChartSeriesType.LINE,selectedPointSize:4,unselectedPointSize:3,colorId:0,lineWidth:1,skipDistance:1,unselectedPointDensityTransparent:0.10,unselectedPointDensityOpaque:0.05,backgroundOpacity:0.5};var LAST_POINT_WIDTH=16;var ChartSeriesComponent={BACKGROUND:0,LINE:1,DOTS:2};function ChartSeries(points,axis,opt_renderingConfig){this.points=points;this.axis=axis;this.useRenderingConfig_(opt_renderingConfig);}
-ChartSeries.prototype={useRenderingConfig_:function(opt_renderingConfig){var config=opt_renderingConfig||{};tv.b.iterItems(DEFAULT_RENDERING_CONFIG,function(key,defaultValue){var value=config[key];if(value===undefined)
-value=defaultValue;this[key+'_']=value;},this);this.topPadding=this.bottomPadding=Math.max(this.selectedPointSize_,this.unselectedPointSize_)/2;},get range(){var range=new tv.b.Range();this.points.forEach(function(point){range.addValue(point.y);},this);return range;},draw:function(ctx,transform,highDetails){if(this.points===undefined||this.points.length===0)
+span.textContent='';this.headingDiv_.appendChild(span);if(this.selectionGenerator_){this.headingLink_=document.createElement('tr-c-a-analysis-link');this.headingLink_.selection=this.selectionGenerator_;this.headingLink_.textContent='';this.headingDiv_.appendChild(this.headingLink_);this.headingLink_.appendChild(document.createTextNode(this.heading_));}else{span=document.createElement('span');span.textContent=this.heading_;this.headingDiv_.appendChild(span);}
+this.appendChild(this.headingDiv_);},draw:function(type,viewLWorld,viewRWorld){throw new Error('draw implementation missing');}};return{HeadingTrack:HeadingTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var EventPresenter=tr.c.EventPresenter;var SelectionState=tr.model.SelectionState;var ChartSeriesType={LINE:0,AREA:1};var DEFAULT_RENDERING_CONFIG={chartType:ChartSeriesType.LINE,selectedPointSize:4,unselectedPointSize:3,colorId:0,lineWidth:1,skipDistance:1,unselectedPointDensityTransparent:0.10,unselectedPointDensityOpaque:0.05,backgroundOpacity:0.5};var LAST_POINT_WIDTH=16;var ChartSeriesComponent={BACKGROUND:0,LINE:1,DOTS:2};function ChartSeries(points,axis,opt_renderingConfig){this.points=points;this.axis=axis;this.useRenderingConfig_(opt_renderingConfig);}
+ChartSeries.prototype={useRenderingConfig_:function(opt_renderingConfig){var config=opt_renderingConfig||{};tr.b.iterItems(DEFAULT_RENDERING_CONFIG,function(key,defaultValue){var value=config[key];if(value===undefined)
+value=defaultValue;this[key+'_']=value;},this);this.topPadding=this.bottomPadding=Math.max(this.selectedPointSize_,this.unselectedPointSize_)/2;},get range(){var range=new tr.b.Range();this.points.forEach(function(point){range.addValue(point.y);},this);return range;},draw:function(ctx,transform,highDetails){if(this.points===undefined||this.points.length===0)
 return;if(this.chartType_===ChartSeriesType.AREA){this.drawComponent_(ctx,transform,ChartSeriesComponent.BACKGROUND,highDetails);}
 if(this.chartType_===ChartSeriesType.LINE||highDetails){this.drawComponent_(ctx,transform,ChartSeriesComponent.LINE,highDetails);}
 this.drawComponent_(ctx,transform,ChartSeriesComponent.DOTS,highDetails);},drawComponent_:function(ctx,transform,component,highDetails){var extraPixels=0;if(component===ChartSeriesComponent.DOTS){extraPixels=Math.max(this.selectedPointSize_,this.unselectedPointSize_);}
 var leftViewX=transform.leftViewX-extraPixels*transform.pixelRatio;var rightViewX=transform.rightViewX+
-extraPixels*transform.pixelRatio;var leftTimestamp=transform.leftTimestamp-extraPixels;var rightTimestamp=transform.rightTimestamp+extraPixels;var firstVisibleIndex=tv.b.findLowIndexInSortedArray(this.points,function(point){return point.x;},leftTimestamp);var lastVisibleIndex=tv.b.findLowIndexInSortedArray(this.points,function(point){return point.x;},rightTimestamp);if(lastVisibleIndex>=this.points.length||this.points[lastVisibleIndex].x>rightTimestamp){lastVisibleIndex--;}
+extraPixels*transform.pixelRatio;var leftTimestamp=transform.leftTimestamp-extraPixels;var rightTimestamp=transform.rightTimestamp+extraPixels;var firstVisibleIndex=tr.b.findLowIndexInSortedArray(this.points,function(point){return point.x;},leftTimestamp);var lastVisibleIndex=tr.b.findLowIndexInSortedArray(this.points,function(point){return point.x;},rightTimestamp);if(lastVisibleIndex>=this.points.length||this.points[lastVisibleIndex].x>rightTimestamp){lastVisibleIndex--;}
 var viewSkipDistance=this.skipDistance_*transform.pixelRatio;var circleRadius;var squareSize;var squareHalfSize;var squareOpacity;switch(component){case ChartSeriesComponent.DOTS:ctx.strokeStyle=EventPresenter.getCounterSeriesColor(this.colorId_,SelectionState.NONE);ctx.lineWidth=transform.pixelRatio;circleRadius=(this.selectedPointSize_/2)*transform.pixelRatio;squareSize=this.unselectedPointSize_*transform.pixelRatio;squareHalfSize=squareSize/2;if(!highDetails){squareOpacity=0;break;}
 var visibleIndexRange=lastVisibleIndex-firstVisibleIndex;if(visibleIndexRange<=0){squareOpacity=1;break;}
 var visibleViewXRange=transform.worldXToViewX(this.points[lastVisibleIndex].x)-
 transform.worldXToViewX(this.points[firstVisibleIndex].x);if(visibleViewXRange===0){squareOpacity=1;break;}
-var density=visibleIndexRange/visibleViewXRange;var clampedDensity=tv.b.clamp(density,this.unselectedPointDensityOpaque_,this.unselectedPointDensityTransparent_);var densityRange=this.unselectedPointDensityTransparent_-
+var density=visibleIndexRange/visibleViewXRange;var clampedDensity=tr.b.clamp(density,this.unselectedPointDensityOpaque_,this.unselectedPointDensityTransparent_);var densityRange=this.unselectedPointDensityTransparent_-
 this.unselectedPointDensityOpaque_;squareOpacity=(this.unselectedPointDensityTransparent_-clampedDensity)/densityRange;break;case ChartSeriesComponent.LINE:ctx.strokeStyle=EventPresenter.getCounterSeriesColor(this.colorId_,SelectionState.NONE);ctx.lineWidth=this.lineWidth_*transform.pixelRatio;break;case ChartSeriesComponent.BACKGROUND:break;default:throw new Error('Invalid component: '+component);}
 var previousViewX=undefined;var previousViewY=undefined;var previousViewYBase=undefined;var lastSelectionState=undefined;var baseSteps=undefined;var startIndex=Math.max(firstVisibleIndex-1,0);for(var i=startIndex;i<this.points.length;i++){var currentPoint=this.points[i];var currentViewX=transform.worldXToViewX(currentPoint.x);if(currentViewX>rightViewX){if(previousViewX!==undefined){previousViewX=currentViewX=rightViewX;if(component===ChartSeriesComponent.BACKGROUND||component===ChartSeriesComponent.LINE){ctx.lineTo(currentViewX,previousViewY);}}
 break;}
@@ -3247,35 +3307,35 @@
 ctx.closePath();ctx.fill();break;default:throw new Error('Not reachable');}}},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){var points=this.points;function getPointWidth(point,i){if(i===points.length-1)
 return LAST_POINT_WIDTH*viewPixWidthWorld;var nextPoint=points[i+1];return nextPoint.x-point.x;}
 function selectPoint(point){point.addToSelection(selection);}
-tv.b.iterateOverIntersectingIntervals(this.points,function(point){return point.x},getPointWidth,loWX,hiWX,selectPoint);},addEventNearToProvidedEventToSelection:function(event,offset,selection){if(this.points===undefined)
-return false;var index=tv.b.findFirstIndexInArray(this.points,function(point){return point.modelItem===event;},this);if(index===-1)
+tr.b.iterateOverIntersectingIntervals(this.points,function(point){return point.x},getPointWidth,loWX,hiWX,selectPoint);},addEventNearToProvidedEventToSelection:function(event,offset,selection){if(this.points===undefined)
+return false;var index=tr.b.findFirstIndexInArray(this.points,function(point){return point.modelItem===event;},this);if(index===-1)
 return false;var newIndex=index+offset;if(newIndex<0||newIndex>=this.points.length)
 return false;this.points[newIndex].addToSelection(selection);return true;},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){if(this.points===undefined)
-return;var item=tv.b.findClosestElementInSortedArray(this.points,function(point){return point.x},worldX,worldMaxDist);if(!item)
-return;item.addToSelection(selection);}};return{ChartSeries:ChartSeries,ChartSeriesType:ChartSeriesType};});'use strict';tv.exportTo('tv.c.tracks',function(){function ChartTransform(displayTransform,axis,trackWidth,trackHeight,topPadding,bottomPadding,pixelRatio){this.pixelRatio=pixelRatio;this.leftViewX=0;this.rightViewX=trackWidth;this.leftTimestamp=displayTransform.xViewToWorld(this.leftViewX);this.rightTimestamp=displayTransform.xViewToWorld(this.rightViewX);this.displayTransform_=displayTransform;this.outerTopViewY=0;this.innerTopViewY=topPadding;this.innerBottomViewY=trackHeight-bottomPadding;this.outerBottomViewY=trackHeight;this.axis_=axis;this.innerHeight_=this.innerBottomViewY-this.innerTopViewY;};ChartTransform.prototype={worldXToViewX:function(worldX){return this.displayTransform_.xWorldToView(worldX);},viewXToWorldX:function(viewX){return this.displayTransform_.xViewToWorld(viewX);},worldYToViewY:function(worldY){var innerHeightCoefficient=1-this.axis_.valueToUnitRange(worldY);return innerHeightCoefficient*this.innerHeight_+this.innerTopViewY;}};return{ChartTransform:ChartTransform};});'use strict';tv.exportTo('tv.c.tracks',function(){var ChartTrack=tv.b.ui.define('chart-track',tv.c.tracks.HeadingTrack);ChartTrack.prototype={__proto__:tv.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tv.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('chart-track');this.series_=undefined;this.axisGuidToAxisData_=undefined;this.topPadding_=undefined;this.bottomPadding_=undefined;},get series(){return this.series_;},set series(series){this.series_=series;this.calculateAxisDataAndPadding_();this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;this.invalidateDrawingContainer();},get hasVisibleContent(){return!!this.series&&this.series.length>0;},calculateAxisDataAndPadding_:function(){if(!this.series_){this.axisGuidToAxisData_=undefined;this.topPadding_=undefined;this.bottomPadding_=undefined;return;}
+return;var item=tr.b.findClosestElementInSortedArray(this.points,function(point){return point.x},worldX,worldMaxDist);if(!item)
+return;item.addToSelection(selection);}};return{ChartSeries:ChartSeries,ChartSeriesType:ChartSeriesType};});'use strict';tr.exportTo('tr.c.tracks',function(){function ChartTransform(displayTransform,axis,trackWidth,trackHeight,topPadding,bottomPadding,pixelRatio){this.pixelRatio=pixelRatio;this.leftViewX=0;this.rightViewX=trackWidth;this.leftTimestamp=displayTransform.xViewToWorld(this.leftViewX);this.rightTimestamp=displayTransform.xViewToWorld(this.rightViewX);this.displayTransform_=displayTransform;this.outerTopViewY=0;this.innerTopViewY=topPadding;this.innerBottomViewY=trackHeight-bottomPadding;this.outerBottomViewY=trackHeight;this.axis_=axis;this.innerHeight_=this.innerBottomViewY-this.innerTopViewY;};ChartTransform.prototype={worldXToViewX:function(worldX){return this.displayTransform_.xWorldToView(worldX);},viewXToWorldX:function(viewX){return this.displayTransform_.xViewToWorld(viewX);},worldYToViewY:function(worldY){var innerHeightCoefficient=1-this.axis_.valueToUnitRange(worldY);return innerHeightCoefficient*this.innerHeight_+this.innerTopViewY;}};return{ChartTransform:ChartTransform};});'use strict';tr.exportTo('tr.c.tracks',function(){var ChartTrack=tr.b.ui.define('chart-track',tr.c.tracks.HeadingTrack);ChartTrack.prototype={__proto__:tr.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tr.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('chart-track');this.series_=undefined;this.axisGuidToAxisData_=undefined;this.topPadding_=undefined;this.bottomPadding_=undefined;},get series(){return this.series_;},set series(series){this.series_=series;this.calculateAxisDataAndPadding_();this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;this.invalidateDrawingContainer();},get hasVisibleContent(){return!!this.series&&this.series.length>0;},calculateAxisDataAndPadding_:function(){if(!this.series_){this.axisGuidToAxisData_=undefined;this.topPadding_=undefined;this.bottomPadding_=undefined;return;}
 var axisGuidToAxisData={};var topPadding=0;var bottomPadding=0;this.series_.forEach(function(series){var axis=series.axis;var axisGuid=axis.guid;if(!(axisGuid in axisGuidToAxisData)){axisGuidToAxisData[axisGuid]={axis:axis,series:[]};}
-axisGuidToAxisData[axisGuid].series.push(series);topPadding=Math.max(topPadding,series.topPadding);bottomPadding=Math.max(bottomPadding,series.bottomPadding);},this);this.axisGuidToAxisData_=axisGuidToAxisData;this.topPadding_=topPadding;this.bottomPadding_=bottomPadding;},draw:function(type,viewLWorld,viewRWorld){switch(type){case tv.c.tracks.DrawType.GENERAL_EVENT:this.drawChart_(viewLWorld,viewRWorld);break;}},drawChart_:function(viewLWorld,viewRWorld){if(!this.series_)
-return;var ctx=this.context();var displayTransform=this.viewport.currentDisplayTransform;var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var highDetails=this.viewport.highDetails;var width=bounds.width*pixelRatio;var height=bounds.height*pixelRatio;var topPadding=this.topPadding_*pixelRatio;var bottomPadding=this.bottomPadding_*pixelRatio;ctx.save();ctx.beginPath();ctx.rect(0,0,width,height);ctx.clip();this.series_.forEach(function(series){var chartTransform=new tv.c.tracks.ChartTransform(displayTransform,series.axis,width,height,topPadding,bottomPadding,pixelRatio);series.draw(ctx,chartTransform,highDetails);},this);ctx.restore();},addEventsToTrackMap:function(eventToTrackMap){this.series_.forEach(function(series){series.points.forEach(function(point){point.addToTrackMap(eventToTrackMap,this);},this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){this.series_.forEach(function(series){series.addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection);},this);},addEventNearToProvidedEventToSelection:function(event,offset,selection){var foundItem=false;this.series_.forEach(function(series){foundItem=foundItem||series.addEventNearToProvidedEventToSelection(event,offset,selection);},this);return foundItem;},addAllEventsMatchingFilterToSelection:function(filter,selection){},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){this.series_.forEach(function(series){series.addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);},this);},autoSetAllAxes:function(opt_config){tv.b.iterItems(this.axisGuidToAxisData_,function(axisGuid,axisData){var axis=axisData.axis;var series=axisData.series;axis.autoSetFromSeries(series,opt_config);},this);},autoSetAxis:function(axis,opt_config){var series=this.axisGuidToAxisData_[axis.guid].series;axis.autoSetFromSeries(series,opt_config);}};return{ChartTrack:ChartTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var CounterTrack=tv.b.ui.define('counter-track',tv.c.tracks.ChartTrack);CounterTrack.prototype={__proto__:tv.c.tracks.ChartTrack.prototype,decorate:function(viewport){tv.c.tracks.ChartTrack.prototype.decorate.call(this,viewport);this.classList.add('counter-track');},get counter(){return this.chart;},set counter(counter){this.heading=counter.name+': ';this.series=CounterTrack.buildChartSeriesFromCounter(counter);this.autoSetAllAxes({expandMax:true});},getModelEventFromItem:function(chartValue){return chartValue;}};CounterTrack.buildChartSeriesFromCounter=function(counter){var numSeries=counter.series.length;var totals=counter.totals;var chartAxis=new tv.c.tracks.ChartAxis(0,undefined);var chartSeries=counter.series.map(function(series,seriesIndex){var chartPoints=series.samples.map(function(sample,sampleIndex){var total=totals[sampleIndex*numSeries+seriesIndex];return new tv.c.tracks.ChartPoint(sample,sample.timestamp,total);});var renderingConfig={chartType:tv.c.tracks.ChartSeriesType.AREA,colorId:series.color};return new tv.c.tracks.ChartSeries(chartPoints,chartAxis,renderingConfig);});chartSeries.reverse();return chartSeries;};return{CounterTrack:CounterTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var EventPresenter=tv.c.EventPresenter;var SelectionState=tv.c.trace_model.SelectionState;var LetterDotTrack=tv.b.ui.define('letter-dot-track',tv.c.tracks.HeadingTrack);LetterDotTrack.prototype={__proto__:tv.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tv.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('letter-dot-track');this.items_=undefined;},get items(){return this.items_;},set items(items){this.items_=items;this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;},get dumpRadiusView(){return 7*(window.devicePixelRatio||1);},draw:function(type,viewLWorld,viewRWorld){if(this.items_===undefined)
-return;switch(type){case tv.c.tracks.DrawType.GENERAL_EVENT:this.drawLetterDots_(viewLWorld,viewRWorld);break;}},drawLetterDots_:function(viewLWorld,viewRWorld){var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var height=bounds.height*pixelRatio;var halfHeight=height*0.5;var twoPi=Math.PI*2;var palette=tv.b.ui.getColorPalette();var highlightIdBoost=tv.b.ui.paletteProperties.highlightIdBoost;var dt=this.viewport.currentDisplayTransform;var dumpRadiusView=this.dumpRadiusView;var itemRadiusWorld=dt.xViewVectorToWorld(height);var items=this.items_;var loI=tv.b.findLowIndexInSortedArray(items,function(item){return item.start;},viewLWorld);var oldFont=ctx.font;ctx.font='400 '+Math.floor(9*pixelRatio)+'px Arial';ctx.strokeStyle='rgb(0,0,0)';ctx.textBaseline='middle';ctx.textAlign='center';var drawItems=function(selected){for(var i=loI;i<items.length;++i){var item=items[i];var x=item.start;if(x-itemRadiusWorld>viewRWorld)
+axisGuidToAxisData[axisGuid].series.push(series);topPadding=Math.max(topPadding,series.topPadding);bottomPadding=Math.max(bottomPadding,series.bottomPadding);},this);this.axisGuidToAxisData_=axisGuidToAxisData;this.topPadding_=topPadding;this.bottomPadding_=bottomPadding;},draw:function(type,viewLWorld,viewRWorld){switch(type){case tr.c.tracks.DrawType.GENERAL_EVENT:this.drawChart_(viewLWorld,viewRWorld);break;}},drawChart_:function(viewLWorld,viewRWorld){if(!this.series_)
+return;var ctx=this.context();var displayTransform=this.viewport.currentDisplayTransform;var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var highDetails=this.viewport.highDetails;var width=bounds.width*pixelRatio;var height=bounds.height*pixelRatio;var topPadding=this.topPadding_*pixelRatio;var bottomPadding=this.bottomPadding_*pixelRatio;ctx.save();ctx.beginPath();ctx.rect(0,0,width,height);ctx.clip();this.series_.forEach(function(series){var chartTransform=new tr.c.tracks.ChartTransform(displayTransform,series.axis,width,height,topPadding,bottomPadding,pixelRatio);series.draw(ctx,chartTransform,highDetails);},this);ctx.restore();},addEventsToTrackMap:function(eventToTrackMap){this.series_.forEach(function(series){series.points.forEach(function(point){point.addToTrackMap(eventToTrackMap,this);},this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){this.series_.forEach(function(series){series.addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection);},this);},addEventNearToProvidedEventToSelection:function(event,offset,selection){var foundItem=false;this.series_.forEach(function(series){foundItem=foundItem||series.addEventNearToProvidedEventToSelection(event,offset,selection);},this);return foundItem;},addAllEventsMatchingFilterToSelection:function(filter,selection){},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){this.series_.forEach(function(series){series.addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);},this);},autoSetAllAxes:function(opt_config){tr.b.iterItems(this.axisGuidToAxisData_,function(axisGuid,axisData){var axis=axisData.axis;var series=axisData.series;axis.autoSetFromSeries(series,opt_config);},this);},autoSetAxis:function(axis,opt_config){var series=this.axisGuidToAxisData_[axis.guid].series;axis.autoSetFromSeries(series,opt_config);}};return{ChartTrack:ChartTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var CounterTrack=tr.b.ui.define('counter-track',tr.c.tracks.ChartTrack);CounterTrack.prototype={__proto__:tr.c.tracks.ChartTrack.prototype,decorate:function(viewport){tr.c.tracks.ChartTrack.prototype.decorate.call(this,viewport);this.classList.add('counter-track');},get counter(){return this.chart;},set counter(counter){this.heading=counter.name+': ';this.series=CounterTrack.buildChartSeriesFromCounter(counter);this.autoSetAllAxes({expandMax:true});},getModelEventFromItem:function(chartValue){return chartValue;}};CounterTrack.buildChartSeriesFromCounter=function(counter){var numSeries=counter.series.length;var totals=counter.totals;var chartAxis=new tr.c.tracks.ChartAxis(0,undefined);var chartSeries=counter.series.map(function(series,seriesIndex){var chartPoints=series.samples.map(function(sample,sampleIndex){var total=totals[sampleIndex*numSeries+seriesIndex];return new tr.c.tracks.ChartPoint(sample,sample.timestamp,total);});var renderingConfig={chartType:tr.c.tracks.ChartSeriesType.AREA,colorId:series.color};return new tr.c.tracks.ChartSeries(chartPoints,chartAxis,renderingConfig);});chartSeries.reverse();return chartSeries;};return{CounterTrack:CounterTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var EventPresenter=tr.c.EventPresenter;var SelectionState=tr.model.SelectionState;var LetterDotTrack=tr.b.ui.define('letter-dot-track',tr.c.tracks.HeadingTrack);LetterDotTrack.prototype={__proto__:tr.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tr.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('letter-dot-track');this.items_=undefined;},get items(){return this.items_;},set items(items){this.items_=items;this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;},get dumpRadiusView(){return 7*(window.devicePixelRatio||1);},draw:function(type,viewLWorld,viewRWorld){if(this.items_===undefined)
+return;switch(type){case tr.c.tracks.DrawType.GENERAL_EVENT:this.drawLetterDots_(viewLWorld,viewRWorld);break;}},drawLetterDots_:function(viewLWorld,viewRWorld){var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var height=bounds.height*pixelRatio;var halfHeight=height*0.5;var twoPi=Math.PI*2;var palette=tr.b.ui.getColorPalette();var highlightIdBoost=tr.b.ui.paletteProperties.highlightIdBoost;var dt=this.viewport.currentDisplayTransform;var dumpRadiusView=this.dumpRadiusView;var itemRadiusWorld=dt.xViewVectorToWorld(height);var items=this.items_;var loI=tr.b.findLowIndexInSortedArray(items,function(item){return item.start;},viewLWorld);var oldFont=ctx.font;ctx.font='400 '+Math.floor(9*pixelRatio)+'px Arial';ctx.strokeStyle='rgb(0,0,0)';ctx.textBaseline='middle';ctx.textAlign='center';var drawItems=function(selected){for(var i=loI;i<items.length;++i){var item=items[i];var x=item.start;if(x-itemRadiusWorld>viewRWorld)
 break;if(item.selected!==selected)
 continue;var xView=dt.xWorldToView(x);ctx.fillStyle=EventPresenter.getSelectableItemColor(item);ctx.beginPath();ctx.arc(xView,halfHeight,dumpRadiusView+0.5,0,twoPi);ctx.fill();if(item.selected){ctx.lineWidth=3;ctx.strokeStyle='rgb(100,100,0)';ctx.stroke();ctx.beginPath();ctx.arc(xView,halfHeight,dumpRadiusView,0,twoPi);ctx.lineWidth=1.5;ctx.strokeStyle='rgb(255,255,0)';ctx.stroke();}else{ctx.lineWidth=1;ctx.strokeStyle='rgb(0,0,0)';ctx.stroke();}
 ctx.fillStyle='rgb(255, 255, 255)';ctx.fillText(item.dotLetter,xView,halfHeight);}};drawItems(false);drawItems(true);ctx.lineWidth=1;ctx.font=oldFont;},addEventsToTrackMap:function(eventToTrackMap){if(this.items_===undefined)
 return;this.items_.forEach(function(item){item.addToTrackMap(eventToTrackMap,this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){if(this.items_===undefined)
-return;var itemRadiusWorld=viewPixWidthWorld*this.dumpRadiusView;tv.b.iterateOverIntersectingIntervals(this.items_,function(x){return x.start-itemRadiusWorld;},function(x){return 2*itemRadiusWorld;},loWX,hiWX,function(item){item.addToSelection(selection);}.bind(this));},addEventNearToProvidedEventToSelection:function(event,offset,selection){if(this.items_===undefined)
-return;var items=this.items_;var index=tv.b.findFirstIndexInArray(items,function(item){return item.modelItem===event;});if(index===-1)
+return;var itemRadiusWorld=viewPixWidthWorld*this.dumpRadiusView;tr.b.iterateOverIntersectingIntervals(this.items_,function(x){return x.start-itemRadiusWorld;},function(x){return 2*itemRadiusWorld;},loWX,hiWX,function(item){item.addToSelection(selection);}.bind(this));},addEventNearToProvidedEventToSelection:function(event,offset,selection){if(this.items_===undefined)
+return;var items=this.items_;var index=tr.b.findFirstIndexInArray(items,function(item){return item.modelItem===event;});if(index===-1)
 return false;var newIndex=index+offset;if(newIndex>=0&&newIndex<items.length){items[newIndex].addToSelection(selection);return true;}
 return false;},addAllEventsMatchingFilterToSelection:function(filter,selection){},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){if(this.items_===undefined)
-return;var item=tv.b.findClosestElementInSortedArray(this.items_,function(x){return x.start;},worldX,worldMaxDist);if(!item)
-return;item.addToSelection(selection);}};function LetterDot(modelItem,dotLetter,colorId,start){tv.c.trace_model.ProxySelectableItem.call(this,modelItem);this.dotLetter=dotLetter;this.colorId=colorId;this.start=start;};LetterDot.prototype={__proto__:tv.c.trace_model.ProxySelectableItem.prototype};return{LetterDotTrack:LetterDotTrack,LetterDot:LetterDot};});'use strict';tv.exportTo('tv.c.tracks',function(){var palette=tv.b.ui.getColorPalette();var startCompare=function(x,y){return x.start-y.start;}
-var FrameTrack=tv.b.ui.define('frame-track',tv.c.tracks.LetterDotTrack);FrameTrack.prototype={__proto__:tv.c.tracks.LetterDotTrack.prototype,decorate:function(viewport){tv.c.tracks.LetterDotTrack.prototype.decorate.call(this,viewport);this.heading='Frames';this.frames_=undefined;this.items=undefined;},get frames(){return this.frames_;},set frames(frames){this.frames_=frames;if(frames===undefined)
-return;this.frames_=this.frames_.slice();this.frames_.sort(startCompare);this.items=this.frames_.map(function(frame){return new FrameDot(frame);});}};function FrameDot(frame){tv.c.tracks.LetterDot.call(this,frame,'F',frame.colorId,frame.start);}
-FrameDot.prototype={__proto__:tv.c.tracks.LetterDot.prototype};return{FrameTrack:FrameTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var TraceModelSettings=tv.c.TraceModelSettings;var MultiRowTrack=tv.b.ui.define('multi-row-track',tv.c.tracks.ContainerTrack);MultiRowTrack.prototype={__proto__:tv.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tv.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.tooltip_='';this.heading_='';this.groupingSource_=undefined;this.itemsToGroup_=undefined;this.defaultToCollapsedWhenSubRowCountMoreThan=1;this.itemsGroupedOnLastUpdateContents_=undefined;this.currentSubRows_=[];this.expanded_=true;},get itemsToGroup(){return this.itemsToGroup_;},setItemsToGroup:function(itemsToGroup,opt_groupingSource){this.itemsToGroup_=itemsToGroup;this.groupingSource_=opt_groupingSource;this.updateContents_();this.updateExpandedStateFromGroupingSource_();},get heading(){return this.heading_;},set heading(h){this.heading_=h;this.updateContents_();},get tooltip(){return this.tooltip_;},set tooltip(t){this.tooltip_=t;this.updateContents_();},get subRows(){return this.currentSubRows_;},get hasVisibleContent(){return this.children.length>0;},get expanded(){return this.expanded_;},set expanded(expanded){expanded=expanded;if(this.expanded_==expanded)
+return;var item=tr.b.findClosestElementInSortedArray(this.items_,function(x){return x.start;},worldX,worldMaxDist);if(!item)
+return;item.addToSelection(selection);}};function LetterDot(modelItem,dotLetter,colorId,start){tr.model.ProxySelectableItem.call(this,modelItem);this.dotLetter=dotLetter;this.colorId=colorId;this.start=start;};LetterDot.prototype={__proto__:tr.model.ProxySelectableItem.prototype};return{LetterDotTrack:LetterDotTrack,LetterDot:LetterDot};});'use strict';tr.exportTo('tr.c.tracks',function(){var palette=tr.b.ui.getColorPalette();var startCompare=function(x,y){return x.start-y.start;}
+var FrameTrack=tr.b.ui.define('frame-track',tr.c.tracks.LetterDotTrack);FrameTrack.prototype={__proto__:tr.c.tracks.LetterDotTrack.prototype,decorate:function(viewport){tr.c.tracks.LetterDotTrack.prototype.decorate.call(this,viewport);this.heading='Frames';this.frames_=undefined;this.items=undefined;},get frames(){return this.frames_;},set frames(frames){this.frames_=frames;if(frames===undefined)
+return;this.frames_=this.frames_.slice();this.frames_.sort(startCompare);this.items=this.frames_.map(function(frame){return new FrameDot(frame);});}};function FrameDot(frame){tr.c.tracks.LetterDot.call(this,frame,'F',frame.colorId,frame.start);}
+FrameDot.prototype={__proto__:tr.c.tracks.LetterDot.prototype};return{FrameTrack:FrameTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var MultiRowTrack=tr.b.ui.define('multi-row-track',tr.c.tracks.ContainerTrack);MultiRowTrack.prototype={__proto__:tr.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tr.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.tooltip_='';this.heading_='';this.groupingSource_=undefined;this.itemsToGroup_=undefined;this.defaultToCollapsedWhenSubRowCountMoreThan=1;this.itemsGroupedOnLastUpdateContents_=undefined;this.currentSubRows_=[];this.expanded_=true;},get itemsToGroup(){return this.itemsToGroup_;},setItemsToGroup:function(itemsToGroup,opt_groupingSource){this.itemsToGroup_=itemsToGroup;this.groupingSource_=opt_groupingSource;this.updateContents_();this.updateExpandedStateFromGroupingSource_();},get heading(){return this.heading_;},set heading(h){this.heading_=h;this.updateContents_();},get tooltip(){return this.tooltip_;},set tooltip(t){this.tooltip_=t;this.updateContents_();},get subRows(){return this.currentSubRows_;},get hasVisibleContent(){return this.children.length>0;},get expanded(){return this.expanded_;},set expanded(expanded){expanded=expanded;if(this.expanded_==expanded)
 return;this.expanded_=expanded;this.expandedStateChanged_();},onHeadingClicked_:function(e){if(this.subRows.length<=1)
-return;this.expanded=!this.expanded;if(this.groupingSource_){var modelSettings=new TraceModelSettings(this.groupingSource_.model);modelSettings.setSettingFor(this.groupingSource_,'expanded',this.expanded);}
-e.stopPropagation();},updateExpandedStateFromGroupingSource_:function(){if(this.groupingSource_){var numSubRows=this.subRows.length;var modelSettings=new TraceModelSettings(this.groupingSource_.model);if(numSubRows>1){var defaultExpanded;if(numSubRows>this.defaultToCollapsedWhenSubRowCountMoreThan){defaultExpanded=false;}else{defaultExpanded=true;}
+return;this.expanded=!this.expanded;if(this.groupingSource_){var modelSettings=new tr.model.ModelSettings(this.groupingSource_.model);modelSettings.setSettingFor(this.groupingSource_,'expanded',this.expanded);}
+e.stopPropagation();},updateExpandedStateFromGroupingSource_:function(){if(this.groupingSource_){var numSubRows=this.subRows.length;var modelSettings=new tr.model.ModelSettings(this.groupingSource_.model);if(numSubRows>1){var defaultExpanded;if(numSubRows>this.defaultToCollapsedWhenSubRowCountMoreThan){defaultExpanded=false;}else{defaultExpanded=true;}
 this.expanded=modelSettings.getSettingFor(this.groupingSource_,'expanded',defaultExpanded);}else{this.expanded=undefined;}}},expandedStateChanged_:function(){var minH=Math.max(2,Math.ceil(18/this.children.length));var h=(this.expanded_?18:minH)+'px';for(var i=0;i<this.children.length;i++)
 this.children[i].height=h;if(this.children.length>0)
-this.children[0].expanded=this.expanded;},updateContents_:function(){tv.c.tracks.ContainerTrack.prototype.updateContents_.call(this);if(!this.itemsToGroup_){this.updateHeadingAndTooltip_();this.currentSubRows_=[];return;}
+this.children[0].expanded=this.expanded;},updateContents_:function(){tr.c.tracks.ContainerTrack.prototype.updateContents_.call(this);if(!this.itemsToGroup_){this.updateHeadingAndTooltip_();this.currentSubRows_=[];return;}
 if(this.areArrayContentsSame_(this.itemsGroupedOnLastUpdateContents_,this.itemsToGroup_)){this.updateHeadingAndTooltip_();return;}
 this.itemsGroupedOnLastUpdateContents_=this.itemsToGroup_;this.detach();if(!this.itemsToGroup_.length){this.currentSubRows_=[];return;}
 var subRows=this.buildSubRows_(this.itemsToGroup_);this.currentSubRows_=subRows;for(var srI=0;srI<subRows.length;srI++){var subRow=subRows[srI];if(!subRow.length)
@@ -3286,40 +3346,40 @@
 return false;if(a.length!=b.length)
 return false;for(var i=0;i<a.length;++i){if(a[i]!=b[i])
 return false;}
-return true;}};return{MultiRowTrack:MultiRowTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var SelectionState=tv.c.trace_model.SelectionState;var EventPresenter=tv.c.EventPresenter;var ObjectInstanceTrack=tv.b.ui.define('object-instance-track',tv.c.tracks.HeadingTrack);ObjectInstanceTrack.prototype={__proto__:tv.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tv.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('object-instance-track');this.objectInstances_=[];this.objectSnapshots_=[];},get objectInstances(){return this.objectInstances_;},set objectInstances(objectInstances){if(!objectInstances||objectInstances.length==0){this.heading='';this.objectInstances_=[];this.objectSnapshots_=[];return;}
-this.heading=objectInstances[0].typeName;this.objectInstances_=objectInstances;this.objectSnapshots_=[];this.objectInstances_.forEach(function(instance){this.objectSnapshots_.push.apply(this.objectSnapshots_,instance.snapshots);},this);this.objectSnapshots_.sort(function(a,b){return a.ts-b.ts;});},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;},get snapshotRadiusView(){return 7*(window.devicePixelRatio||1);},draw:function(type,viewLWorld,viewRWorld){switch(type){case tv.c.tracks.DrawType.GENERAL_EVENT:this.drawLetterDots_(viewLWorld,viewRWorld);break;}},drawLetterDots_:function(viewLWorld,viewRWorld){var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var height=bounds.height*pixelRatio;var halfHeight=height*0.5;var twoPi=Math.PI*2;var dt=this.viewport.currentDisplayTransform;var snapshotRadiusView=this.snapshotRadiusView;var snapshotRadiusWorld=dt.xViewVectorToWorld(height);var loI;ctx.save();dt.applyTransformToCanvas(ctx);var objectInstances=this.objectInstances_;var loI=tv.b.findLowIndexInSortedArray(objectInstances,function(instance){return instance.deletionTs;},viewLWorld);ctx.strokeStyle='rgb(0,0,0)';for(var i=loI;i<objectInstances.length;++i){var instance=objectInstances[i];var x=instance.creationTs;if(x>viewRWorld)
+return true;}};return{MultiRowTrack:MultiRowTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var SelectionState=tr.model.SelectionState;var EventPresenter=tr.c.EventPresenter;var ObjectInstanceTrack=tr.b.ui.define('object-instance-track',tr.c.tracks.HeadingTrack);ObjectInstanceTrack.prototype={__proto__:tr.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tr.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('object-instance-track');this.objectInstances_=[];this.objectSnapshots_=[];},get objectInstances(){return this.objectInstances_;},set objectInstances(objectInstances){if(!objectInstances||objectInstances.length==0){this.heading='';this.objectInstances_=[];this.objectSnapshots_=[];return;}
+this.heading=objectInstances[0].typeName;this.objectInstances_=objectInstances;this.objectSnapshots_=[];this.objectInstances_.forEach(function(instance){this.objectSnapshots_.push.apply(this.objectSnapshots_,instance.snapshots);},this);this.objectSnapshots_.sort(function(a,b){return a.ts-b.ts;});},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;},get snapshotRadiusView(){return 7*(window.devicePixelRatio||1);},draw:function(type,viewLWorld,viewRWorld){switch(type){case tr.c.tracks.DrawType.GENERAL_EVENT:this.drawLetterDots_(viewLWorld,viewRWorld);break;}},drawLetterDots_:function(viewLWorld,viewRWorld){var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var height=bounds.height*pixelRatio;var halfHeight=height*0.5;var twoPi=Math.PI*2;var dt=this.viewport.currentDisplayTransform;var snapshotRadiusView=this.snapshotRadiusView;var snapshotRadiusWorld=dt.xViewVectorToWorld(height);var loI;ctx.save();dt.applyTransformToCanvas(ctx);var objectInstances=this.objectInstances_;var loI=tr.b.findLowIndexInSortedArray(objectInstances,function(instance){return instance.deletionTs;},viewLWorld);ctx.strokeStyle='rgb(0,0,0)';for(var i=loI;i<objectInstances.length;++i){var instance=objectInstances[i];var x=instance.creationTs;if(x>viewRWorld)
 break;var right=instance.deletionTs==Number.MAX_VALUE?viewRWorld:instance.deletionTs;ctx.fillStyle=EventPresenter.getObjectInstanceColor(instance);ctx.fillRect(x,pixelRatio,right-x,height-2*pixelRatio);}
-ctx.restore();var objectSnapshots=this.objectSnapshots_;loI=tv.b.findLowIndexInSortedArray(objectSnapshots,function(snapshot){return snapshot.ts+snapshotRadiusWorld;},viewLWorld);for(var i=loI;i<objectSnapshots.length;++i){var snapshot=objectSnapshots[i];var x=snapshot.ts;if(x-snapshotRadiusWorld>viewRWorld)
+ctx.restore();var objectSnapshots=this.objectSnapshots_;loI=tr.b.findLowIndexInSortedArray(objectSnapshots,function(snapshot){return snapshot.ts+snapshotRadiusWorld;},viewLWorld);for(var i=loI;i<objectSnapshots.length;++i){var snapshot=objectSnapshots[i];var x=snapshot.ts;if(x-snapshotRadiusWorld>viewRWorld)
 break;var xView=dt.xWorldToView(x);ctx.fillStyle=EventPresenter.getObjectSnapshotColor(snapshot);ctx.beginPath();ctx.arc(xView,halfHeight,snapshotRadiusView,0,twoPi);ctx.fill();if(snapshot.selected){ctx.lineWidth=5;ctx.strokeStyle='rgb(100,100,0)';ctx.stroke();ctx.beginPath();ctx.arc(xView,halfHeight,snapshotRadiusView-1,0,twoPi);ctx.lineWidth=2;ctx.strokeStyle='rgb(255,255,0)';ctx.stroke();}else{ctx.lineWidth=1;ctx.strokeStyle='rgb(0,0,0)';ctx.stroke();}}
 ctx.lineWidth=1;var selectionState=SelectionState.NONE;if(objectInstances.length&&objectInstances[0].selectionState===SelectionState.DIMMED){selectionState=SelectionState.DIMMED;}
 if(selectionState===SelectionState.DIMMED){var width=bounds.width*pixelRatio;ctx.fillStyle='rgba(255,255,255,0.5)';ctx.fillRect(0,0,width,height);ctx.restore();}},addEventsToTrackMap:function(eventToTrackMap){if(this.objectInstance_!==undefined){this.objectInstance_.forEach(function(obj){eventToTrackMap.addEvent(obj,this);},this);}
 if(this.objectSnapshots_!==undefined){this.objectSnapshots_.forEach(function(obj){eventToTrackMap.addEvent(obj,this);},this);}},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){var foundSnapshot=false;function onSnapshot(snapshot){selection.push(snapshot);foundSnapshot=true;}
-var snapshotRadiusView=this.snapshotRadiusView;var snapshotRadiusWorld=viewPixWidthWorld*snapshotRadiusView;tv.b.iterateOverIntersectingIntervals(this.objectSnapshots_,function(x){return x.ts-snapshotRadiusWorld;},function(x){return 2*snapshotRadiusWorld;},loWX,hiWX,onSnapshot);if(foundSnapshot)
-return;tv.b.iterateOverIntersectingIntervals(this.objectInstances_,function(x){return x.creationTs;},function(x){return x.deletionTs-x.creationTs;},loWX,hiWX,selection.push.bind(selection));},addEventNearToProvidedEventToSelection:function(event,offset,selection){var events;if(event instanceof tv.c.trace_model.ObjectSnapshot)
-events=this.objectSnapshots_;else if(event instanceof tv.c.trace_model.ObjectInstance)
+var snapshotRadiusView=this.snapshotRadiusView;var snapshotRadiusWorld=viewPixWidthWorld*snapshotRadiusView;tr.b.iterateOverIntersectingIntervals(this.objectSnapshots_,function(x){return x.ts-snapshotRadiusWorld;},function(x){return 2*snapshotRadiusWorld;},loWX,hiWX,onSnapshot);if(foundSnapshot)
+return;tr.b.iterateOverIntersectingIntervals(this.objectInstances_,function(x){return x.creationTs;},function(x){return x.deletionTs-x.creationTs;},loWX,hiWX,selection.push.bind(selection));},addEventNearToProvidedEventToSelection:function(event,offset,selection){var events;if(event instanceof tr.model.ObjectSnapshot)
+events=this.objectSnapshots_;else if(event instanceof tr.model.ObjectInstance)
 events=this.objectInstances_;else
 throw new Error('Unrecognized event');var index=events.indexOf(event);var newIndex=index+offset;if(newIndex>=0&&newIndex<events.length){selection.push(events[newIndex]);return true;}
-return false;},addAllEventsMatchingFilterToSelection:function(filter,selection){},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){var snapshot=tv.b.findClosestElementInSortedArray(this.objectSnapshots_,function(x){return x.ts;},worldX,worldMaxDist);if(!snapshot)
-return;selection.push(snapshot);}};var options=new tv.b.ExtensionRegistryOptions(tv.b.TYPE_BASED_REGISTRY_MODE);tv.b.decorateExtensionRegistry(ObjectInstanceTrack,options);return{ObjectInstanceTrack:ObjectInstanceTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var ObjectInstanceGroupTrack=tv.b.ui.define('object-instance-group-track',tv.c.tracks.MultiRowTrack);ObjectInstanceGroupTrack.prototype={__proto__:tv.c.tracks.MultiRowTrack.prototype,decorate:function(viewport){tv.c.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);this.classList.add('object-instance-group-track');this.objectInstances_=undefined;},get objectInstances(){return this.itemsToGroup;},set objectInstances(objectInstances){this.setItemsToGroup(objectInstances);},addSubTrack_:function(objectInstances){var hasMultipleRows=this.subRows.length>1;var track=new tv.c.tracks.ObjectInstanceTrack(this.viewport);track.objectInstances=objectInstances;this.appendChild(track);return track;},buildSubRows_:function(objectInstances){objectInstances.sort(function(x,y){return x.creationTs-y.creationTs;});var subRows=[];for(var i=0;i<objectInstances.length;i++){var objectInstance=objectInstances[i];var found=false;for(var j=0;j<subRows.length;j++){var subRow=subRows[j];var lastItemInSubRow=subRow[subRow.length-1];if(objectInstance.creationTs>=lastItemInSubRow.deletionTs){found=true;subRow.push(objectInstance);break;}}
+return false;},addAllEventsMatchingFilterToSelection:function(filter,selection){},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){var snapshot=tr.b.findClosestElementInSortedArray(this.objectSnapshots_,function(x){return x.ts;},worldX,worldMaxDist);if(!snapshot)
+return;selection.push(snapshot);}};var options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);tr.b.decorateExtensionRegistry(ObjectInstanceTrack,options);return{ObjectInstanceTrack:ObjectInstanceTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var ObjectInstanceGroupTrack=tr.b.ui.define('object-instance-group-track',tr.c.tracks.MultiRowTrack);ObjectInstanceGroupTrack.prototype={__proto__:tr.c.tracks.MultiRowTrack.prototype,decorate:function(viewport){tr.c.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);this.classList.add('object-instance-group-track');this.objectInstances_=undefined;},get objectInstances(){return this.itemsToGroup;},set objectInstances(objectInstances){this.setItemsToGroup(objectInstances);},addSubTrack_:function(objectInstances){var hasMultipleRows=this.subRows.length>1;var track=new tr.c.tracks.ObjectInstanceTrack(this.viewport);track.objectInstances=objectInstances;this.appendChild(track);return track;},buildSubRows_:function(objectInstances){objectInstances.sort(function(x,y){return x.creationTs-y.creationTs;});var subRows=[];for(var i=0;i<objectInstances.length;i++){var objectInstance=objectInstances[i];var found=false;for(var j=0;j<subRows.length;j++){var subRow=subRows[j];var lastItemInSubRow=subRow[subRow.length-1];if(objectInstance.creationTs>=lastItemInSubRow.deletionTs){found=true;subRow.push(objectInstance);break;}}
 if(!found){var subRow=[objectInstance];subRows.push(subRow);}}
-return subRows;},updateHeadingAndTooltip_:function(){}};return{ObjectInstanceGroupTrack:ObjectInstanceGroupTrack};});'use strict';tv.exportTo('tv.c',function(){function FastRectRenderer(ctx,minRectSize,maxMergeDist,pallette){this.ctx_=ctx;this.minRectSize_=minRectSize;this.maxMergeDist_=maxMergeDist;this.pallette_=pallette;}
+return subRows;},updateHeadingAndTooltip_:function(){}};return{ObjectInstanceGroupTrack:ObjectInstanceGroupTrack};});'use strict';tr.exportTo('tr.c',function(){function FastRectRenderer(ctx,minRectSize,maxMergeDist,pallette){this.ctx_=ctx;this.minRectSize_=minRectSize;this.maxMergeDist_=maxMergeDist;this.pallette_=pallette;}
 FastRectRenderer.prototype={y_:0,h_:0,merging_:false,mergeStartX_:0,mergeCurRight_:0,mergedColorId_:0,mergedAlpha_:0,setYandH:function(y,h){if(this.y_===y&&this.h_===h)
 return;this.flush();this.y_=y;this.h_=h;},fillRect:function(x,w,colorId,alpha){var r=x+w;if(w<this.minRectSize_){if(r-this.mergeStartX_>this.maxMergeDist_)
 this.flush();if(!this.merging_){this.merging_=true;this.mergeStartX_=x;this.mergeCurRight_=r;this.mergedColorId_=colorId;this.mergedAlpha_=alpha;}else{this.mergeCurRight_=r;if(this.mergedAlpha_<alpha||(this.mergedAlpha_===alpha&&this.mergedColorId_<colorId)){this.mergedAlpha_=alpha;this.mergedColorId_=colorId;}}}else{if(this.merging_)
-this.flush();this.ctx_.fillStyle=this.pallette_[colorId];this.ctx_.globalAlpha=alpha;this.ctx_.fillRect(x,this.y_,w,this.h_);}},flush:function(){if(this.merging_){this.ctx_.fillStyle=this.pallette_[this.mergedColorId_];this.ctx_.globalAlpha=this.mergedAlpha_;this.ctx_.fillRect(this.mergeStartX_,this.y_,this.mergeCurRight_-this.mergeStartX_,this.h_);this.merging_=false;}}};return{FastRectRenderer:FastRectRenderer};});'use strict';tv.exportTo('tv.c.tracks',function(){var RectTrack=tv.b.ui.define('rect-track',tv.c.tracks.HeadingTrack);RectTrack.prototype={__proto__:tv.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tv.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('rect-track');this.asyncStyle_=false;this.rects_=null;},get asyncStyle(){return this.asyncStyle_;},set asyncStyle(v){this.asyncStyle_=!!v;},get rects(){return this.rects_;},set rects(rects){this.rects_=rects||[];this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;this.invalidateDrawingContainer();},get hasVisibleContent(){return this.rects_.length>0;},draw:function(type,viewLWorld,viewRWorld){switch(type){case tv.c.tracks.DrawType.GENERAL_EVENT:this.drawRects_(viewLWorld,viewRWorld);break;}},drawRects_:function(viewLWorld,viewRWorld){var ctx=this.context();ctx.save();var bounds=this.getBoundingClientRect();tv.c.drawSlices(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.rects_,this.asyncStyle_);ctx.restore();if(bounds.height<=6)
+this.flush();this.ctx_.fillStyle=this.pallette_[colorId];this.ctx_.globalAlpha=alpha;this.ctx_.fillRect(x,this.y_,w,this.h_);}},flush:function(){if(this.merging_){this.ctx_.fillStyle=this.pallette_[this.mergedColorId_];this.ctx_.globalAlpha=this.mergedAlpha_;this.ctx_.fillRect(this.mergeStartX_,this.y_,this.mergeCurRight_-this.mergeStartX_,this.h_);this.merging_=false;}}};return{FastRectRenderer:FastRectRenderer};});'use strict';tr.exportTo('tr.c.tracks',function(){var RectTrack=tr.b.ui.define('rect-track',tr.c.tracks.HeadingTrack);RectTrack.prototype={__proto__:tr.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tr.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('rect-track');this.asyncStyle_=false;this.rects_=null;},get asyncStyle(){return this.asyncStyle_;},set asyncStyle(v){this.asyncStyle_=!!v;},get rects(){return this.rects_;},set rects(rects){this.rects_=rects||[];this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;this.invalidateDrawingContainer();},get hasVisibleContent(){return this.rects_.length>0;},draw:function(type,viewLWorld,viewRWorld){switch(type){case tr.c.tracks.DrawType.GENERAL_EVENT:this.drawRects_(viewLWorld,viewRWorld);break;}},drawRects_:function(viewLWorld,viewRWorld){var ctx=this.context();ctx.save();var bounds=this.getBoundingClientRect();tr.c.drawSlices(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.rects_,this.asyncStyle_);ctx.restore();if(bounds.height<=6)
 return;var fontSize,yOffset;if(bounds.height<15){fontSize=6;yOffset=1.0;}else{fontSize=10;yOffset=2.5;}
-tv.c.drawLabels(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,this.rects_,this.asyncStyle_,fontSize,yOffset);},addEventsToTrackMap:function(eventToTrackMap){if(this.rects_===undefined||this.rects_===null)
+tr.c.drawLabels(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,this.rects_,this.asyncStyle_,fontSize,yOffset);},addEventsToTrackMap:function(eventToTrackMap){if(this.rects_===undefined||this.rects_===null)
 return;this.rects_.forEach(function(rect){rect.addToTrackMap(eventToTrackMap,this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){function onRect(rect){rect.addToSelection(selection);}
-onRect=onRect.bind(this);tv.b.iterateOverIntersectingIntervals(this.rects_,function(x){return x.start;},function(x){return x.duration;},loWX,hiWX,onRect);},addEventNearToProvidedEventToSelection:function(event,offset,selection){var index=tv.b.findFirstIndexInArray(this.rects_,function(rect){return rect.modelItem===event;});if(index===-1)
+onRect=onRect.bind(this);tr.b.iterateOverIntersectingIntervals(this.rects_,function(x){return x.start;},function(x){return x.duration;},loWX,hiWX,onRect);},addEventNearToProvidedEventToSelection:function(event,offset,selection){var index=tr.b.findFirstIndexInArray(this.rects_,function(rect){return rect.modelItem===event;});if(index===-1)
 return false;var newIndex=index+offset;if(newIndex<0||newIndex>=this.rects_.length)
 return false;this.rects_[newIndex].addToSelection(selection);return true;},addAllEventsMatchingFilterToSelection:function(filter,selection){for(var i=0;i<this.rects_.length;++i){var modelItem=this.rects_[i].modelItem;if(!modelItem)
 continue;if(filter.matchSlice(modelItem))
-selection.push(modelItem);}},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){var rect=tv.b.findClosestIntervalInSortedIntervals(this.rects_,function(x){return x.start;},function(x){return x.end;},worldX,worldMaxDist);if(!rect)
-return;rect.addToSelection(selection);}};function Rect(modelItem,title,colorId,start,duration){tv.c.trace_model.ProxySelectableItem.call(this,modelItem);this.title=title;this.colorId=colorId;this.start=start;this.duration=duration;this.end=start+duration;};Rect.prototype={__proto__:tv.c.trace_model.ProxySelectableItem.prototype};return{RectTrack:RectTrack,Rect:Rect};});'use strict';tv.exportTo('tv.c.tracks',function(){var ProcessSummaryTrack=tv.b.ui.define('process-summary-track',tv.c.tracks.RectTrack);ProcessSummaryTrack.buildRectsFromProcess=function(process){if(!process)
+selection.push(modelItem);}},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){var rect=tr.b.findClosestIntervalInSortedIntervals(this.rects_,function(x){return x.start;},function(x){return x.end;},worldX,worldMaxDist);if(!rect)
+return;rect.addToSelection(selection);}};function Rect(modelItem,title,colorId,start,duration){tr.model.ProxySelectableItem.call(this,modelItem);this.title=title;this.colorId=colorId;this.start=start;this.duration=duration;this.end=start+duration;};Rect.prototype={__proto__:tr.model.ProxySelectableItem.prototype};return{RectTrack:RectTrack,Rect:Rect};});'use strict';tr.exportTo('tr.c.tracks',function(){var ProcessSummaryTrack=tr.b.ui.define('process-summary-track',tr.c.tracks.RectTrack);ProcessSummaryTrack.buildRectsFromProcess=function(process){if(!process)
 return[];var ops=[];var pushOp=function(isStart,time,slice){ops.push({isStart:isStart,time:time,slice:slice});};for(var tid in process.threads){var sliceGroup=process.threads[tid].sliceGroup;sliceGroup.topLevelSlices.forEach(function(slice){pushOp(true,slice.start,undefined);pushOp(false,slice.end,undefined);});sliceGroup.slices.forEach(function(slice){if(slice.important){pushOp(true,slice.start,slice);pushOp(false,slice.end,slice);}});}
-ops.sort(function(a,b){return a.time-b.time;});var rects=[];var genericColorId=tv.b.ui.getColorIdForReservedName('generic_work');var pushRect=function(start,end,slice){rects.push(new tv.c.tracks.Rect(slice,slice?slice.title:'',slice?slice.colorId:genericColorId,start,end-start));}
+ops.sort(function(a,b){return a.time-b.time;});var rects=[];var genericColorId=tr.b.ui.getColorIdForReservedName('generic_work');var pushRect=function(start,end,slice){rects.push(new tr.c.tracks.Rect(slice,slice?slice.title:'',slice?slice.colorId:genericColorId,start,end-start));}
 var depth=0;var currentSlice=undefined;var lastStart=undefined;ops.forEach(function(op){depth+=op.isStart?1:-1;if(currentSlice){if(!op.isStart&&op.slice==currentSlice){pushRect(lastStart,op.time,currentSlice);lastStart=depth>=1?op.time:undefined;currentSlice=undefined;}}else{if(op.isStart){if(depth==1){lastStart=op.time;currentSlice=op.slice;}else if(op.slice){if(op.time!=lastStart){pushRect(lastStart,op.time,undefined);lastStart=op.time;}
-currentSlice=op.slice;}}else{if(depth==0){pushRect(lastStart,op.time,undefined);lastStart=undefined;}}}});return rects;};ProcessSummaryTrack.prototype={__proto__:tv.c.tracks.RectTrack.prototype,decorate:function(viewport){tv.c.tracks.RectTrack.prototype.decorate.call(this,viewport);},get process(){return this.process_;},set process(process){this.process_=process;this.rects=ProcessSummaryTrack.buildRectsFromProcess(process);}};return{ProcessSummaryTrack:ProcessSummaryTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var SpacingTrack=tv.b.ui.define('spacing-track',tv.c.tracks.HeadingTrack);SpacingTrack.prototype={__proto__:tv.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tv.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('spacing-track');},draw:function(type,viewLWorld,viewRWorld){},addAllEventsMatchingFilterToSelection:function(filter,selection){}};return{SpacingTrack:SpacingTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var SampleTrack=tv.b.ui.define('sample-track',tv.c.tracks.RectTrack);SampleTrack.prototype={__proto__:tv.c.tracks.RectTrack.prototype,decorate:function(viewport){tv.c.tracks.RectTrack.prototype.decorate.call(this,viewport);},get samples(){return this.rects;},set samples(samples){this.rects=samples;}};return{SampleTrack:SampleTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var SliceTrack=tv.b.ui.define('slice-track',tv.c.tracks.RectTrack);SliceTrack.prototype={__proto__:tv.c.tracks.RectTrack.prototype,decorate:function(viewport){tv.c.tracks.RectTrack.prototype.decorate.call(this,viewport);},get slices(){return this.rects;},set slices(slices){this.rects=slices;}};return{SliceTrack:SliceTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var SliceGroupTrack=tv.b.ui.define('slice-group-track',tv.c.tracks.MultiRowTrack);SliceGroupTrack.prototype={__proto__:tv.c.tracks.MultiRowTrack.prototype,decorate:function(viewport){tv.c.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);this.classList.add('slice-group-track');this.group_=undefined;this.defaultToCollapsedWhenSubRowCountMoreThan=100;},addSubTrack_:function(slices){var track=new tv.c.tracks.SliceTrack(this.viewport);track.slices=slices;this.appendChild(track);return track;},get group(){return this.group_;},set group(group){this.group_=group;this.setItemsToGroup(this.group_.slices,this.group_);},get eventContainer(){return this.group;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.group,this);},buildSubRows_:function(slices){if(!slices.length)
+currentSlice=op.slice;}}else{if(depth==0){pushRect(lastStart,op.time,undefined);lastStart=undefined;}}}});return rects;};ProcessSummaryTrack.prototype={__proto__:tr.c.tracks.RectTrack.prototype,decorate:function(viewport){tr.c.tracks.RectTrack.prototype.decorate.call(this,viewport);},get process(){return this.process_;},set process(process){this.process_=process;this.rects=ProcessSummaryTrack.buildRectsFromProcess(process);}};return{ProcessSummaryTrack:ProcessSummaryTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var SpacingTrack=tr.b.ui.define('spacing-track',tr.c.tracks.HeadingTrack);SpacingTrack.prototype={__proto__:tr.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tr.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('spacing-track');},draw:function(type,viewLWorld,viewRWorld){},addAllEventsMatchingFilterToSelection:function(filter,selection){}};return{SpacingTrack:SpacingTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var SampleTrack=tr.b.ui.define('sample-track',tr.c.tracks.RectTrack);SampleTrack.prototype={__proto__:tr.c.tracks.RectTrack.prototype,decorate:function(viewport){tr.c.tracks.RectTrack.prototype.decorate.call(this,viewport);},get samples(){return this.rects;},set samples(samples){this.rects=samples;}};return{SampleTrack:SampleTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var SliceTrack=tr.b.ui.define('slice-track',tr.c.tracks.RectTrack);SliceTrack.prototype={__proto__:tr.c.tracks.RectTrack.prototype,decorate:function(viewport){tr.c.tracks.RectTrack.prototype.decorate.call(this,viewport);},get slices(){return this.rects;},set slices(slices){this.rects=slices;}};return{SliceTrack:SliceTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var SliceGroupTrack=tr.b.ui.define('slice-group-track',tr.c.tracks.MultiRowTrack);SliceGroupTrack.prototype={__proto__:tr.c.tracks.MultiRowTrack.prototype,decorate:function(viewport){tr.c.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);this.classList.add('slice-group-track');this.group_=undefined;this.defaultToCollapsedWhenSubRowCountMoreThan=100;},addSubTrack_:function(slices){var track=new tr.c.tracks.SliceTrack(this.viewport);track.slices=slices;this.appendChild(track);return track;},get group(){return this.group_;},set group(group){this.group_=group;this.setItemsToGroup(this.group_.slices,this.group_);},get eventContainer(){return this.group;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.group,this);},buildSubRows_:function(slices){if(!slices.length)
 return[];var ops=[];for(var i=0;i<slices.length;i++){if(slices[i].subSlices)
 slices[i].subSlices.splice(0,slices[i].subSlices.length);ops.push(i);}
 ops.sort(function(ix,iy){var x=slices[ix];var y=slices[iy];if(x.start!=y.start)
@@ -3330,7 +3390,7 @@
 insertedSlice.subSlices.push(slice);inserted=true;break;}}
 if(inserted)
 continue;subRows[0].push(slice);}
-return subRows;}};return{SliceGroupTrack:SliceGroupTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var AsyncSliceGroupTrack=tv.b.ui.define('async-slice-group-track',tv.c.tracks.MultiRowTrack);AsyncSliceGroupTrack.prototype={__proto__:tv.c.tracks.MultiRowTrack.prototype,decorate:function(viewport){tv.c.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);this.classList.add('async-slice-group-track');this.group_=undefined;},addSubTrack_:function(slices){var track=new tv.c.tracks.SliceTrack(this.viewport);track.slices=slices;this.appendChild(track);track.asyncStyle=true;return track;},get group(){return this.group_;},set group(group){this.group_=group;this.setItemsToGroup(this.group_.slices,this.group_);},get eventContainer(){return this.group;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.group,this);},buildSubRows_:function(slices,opt_skipSort){if(!opt_skipSort){slices.sort(function(x,y){return x.start-y.start;});}
+return subRows;}};return{SliceGroupTrack:SliceGroupTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var AsyncSliceGroupTrack=tr.b.ui.define('async-slice-group-track',tr.c.tracks.MultiRowTrack);AsyncSliceGroupTrack.prototype={__proto__:tr.c.tracks.MultiRowTrack.prototype,decorate:function(viewport){tr.c.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);this.classList.add('async-slice-group-track');this.group_=undefined;},addSubTrack_:function(slices){var track=new tr.c.tracks.SliceTrack(this.viewport);track.slices=slices;this.appendChild(track);track.asyncStyle=true;return track;},get group(){return this.group_;},set group(group){this.group_=group;this.setItemsToGroup(this.group_.slices,this.group_);},get eventContainer(){return this.group;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.group,this);},buildSubRows_:function(slices,opt_skipSort){if(!opt_skipSort){slices.sort(function(x,y){return x.start-y.start;});}
 var findLevel=function(sliceToPut,rows,n){if(n>=rows.length)
 return true;var subRow=rows[n];var lastSliceInSubRow=subRow[subRow.length-1];if(sliceToPut.start>=lastSliceInSubRow.end){if(sliceToPut.subSlices===undefined||sliceToPut.subSlices.length===0){return true;}
 for(var i=0;i<sliceToPut.subSlices.length;i++){if(!findLevel(sliceToPut.subSlices[i],rows,n+1))
@@ -3343,86 +3403,88 @@
 return;if(level===rows.length)
 rows.push([]);for(var h=0;h<subSlices.length;h++){rows[level].push(subSlices[h]);fitSubSlicesRecursively(subSlices[h].subSlices,level+1,rows);}}
 fitSubSlicesRecursively(slice.subSlices,index+1,subRows);}
-return subRows;}};return{AsyncSliceGroupTrack:AsyncSliceGroupTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var ThreadTrack=tv.b.ui.define('thread-track',tv.c.tracks.ContainerTrack);ThreadTrack.prototype={__proto__:tv.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tv.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.classList.add('thread-track');},get thread(){return this.thread_;},set thread(thread){this.thread_=thread;this.updateContents_();},get hasVisibleContent(){return this.tracks_.length>0;},get eventContainer(){return this.thread;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.thread,this);for(var i=0;i<this.childNodes.length;++i)
+return subRows;}};return{AsyncSliceGroupTrack:AsyncSliceGroupTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var ThreadTrack=tr.b.ui.define('thread-track',tr.c.tracks.ContainerTrack);ThreadTrack.prototype={__proto__:tr.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tr.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.classList.add('thread-track');},get thread(){return this.thread_;},set thread(thread){this.thread_=thread;this.updateContents_();},get hasVisibleContent(){return this.tracks_.length>0;},get eventContainer(){return this.thread;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.thread,this);for(var i=0;i<this.childNodes.length;++i)
 this.childNodes[i].addContainersToTrackMap(containerToTrackMap);},updateContents_:function(){this.detach();if(!this.thread_)
 return;this.heading=this.thread_.userFriendlyName+': ';this.tooltip=this.thread_.userFriendlyDetails;if(this.thread_.asyncSliceGroup.length)
-this.appendAsyncSliceTracks_();this.appendThreadSamplesTracks_();if(this.thread_.timeSlices){var timeSlicesTrack=new tv.c.tracks.SliceTrack(this.viewport);timeSlicesTrack.heading='';timeSlicesTrack.height=tv.c.THIN_SLICE_HEIGHT+'px';timeSlicesTrack.slices=this.thread_.timeSlices;if(timeSlicesTrack.hasVisibleContent)
+this.appendAsyncSliceTracks_();this.appendThreadSamplesTracks_();if(this.thread_.timeSlices){var timeSlicesTrack=new tr.c.tracks.SliceTrack(this.viewport);timeSlicesTrack.heading='';timeSlicesTrack.height=tr.c.THIN_SLICE_HEIGHT+'px';timeSlicesTrack.slices=this.thread_.timeSlices;if(timeSlicesTrack.hasVisibleContent)
 this.appendChild(timeSlicesTrack);}
-if(this.thread_.sliceGroup.length){var track=new tv.c.tracks.SliceGroupTrack(this.viewport);track.heading=this.thread_.userFriendlyName;track.tooltip=this.thread_.userFriendlyDetails;track.group=this.thread_.sliceGroup;if(track.hasVisibleContent)
-this.appendChild(track);}},appendAsyncSliceTracks_:function(){var subGroups=this.thread_.asyncSliceGroup.viewSubGroups;subGroups.forEach(function(subGroup){var asyncTrack=new tv.c.tracks.AsyncSliceGroupTrack(this.viewport);var title=subGroup.slices[0].viewSubGroupTitle;asyncTrack.group=subGroup;asyncTrack.heading=title;if(asyncTrack.hasVisibleContent)
+if(this.thread_.sliceGroup.length){var track=new tr.c.tracks.SliceGroupTrack(this.viewport);track.heading=this.thread_.userFriendlyName;track.tooltip=this.thread_.userFriendlyDetails;track.group=this.thread_.sliceGroup;if(track.hasVisibleContent)
+this.appendChild(track);}},appendAsyncSliceTracks_:function(){var subGroups=this.thread_.asyncSliceGroup.viewSubGroups;subGroups.forEach(function(subGroup){var asyncTrack=new tr.c.tracks.AsyncSliceGroupTrack(this.viewport);var title=subGroup.slices[0].viewSubGroupTitle;asyncTrack.group=subGroup;asyncTrack.heading=title;if(asyncTrack.hasVisibleContent)
 this.appendChild(asyncTrack);},this);},appendThreadSamplesTracks_:function(){var threadSamples=this.thread_.samples;if(threadSamples===undefined||threadSamples.length===0)
 return;var samplesByTitle={};threadSamples.forEach(function(sample){if(samplesByTitle[sample.title]===undefined)
-samplesByTitle[sample.title]=[];samplesByTitle[sample.title].push(sample);});var sampleTitles=tv.b.dictionaryKeys(samplesByTitle);sampleTitles.sort();sampleTitles.forEach(function(sampleTitle){var samples=samplesByTitle[sampleTitle];var samplesTrack=new tv.c.tracks.SampleTrack(this.viewport);samplesTrack.group=this.thread_;samplesTrack.samples=samples;samplesTrack.heading=this.thread_.userFriendlyName+': '+
-sampleTitle;samplesTrack.tooltip=this.thread_.userFriendlyDetails;samplesTrack.selectionGenerator=function(){var selection=new tv.c.Selection();for(var i=0;i<samplesTrack.samples.length;i++){selection.push(samplesTrack.samples[i]);}
+samplesByTitle[sample.title]=[];samplesByTitle[sample.title].push(sample);});var sampleTitles=tr.b.dictionaryKeys(samplesByTitle);sampleTitles.sort();sampleTitles.forEach(function(sampleTitle){var samples=samplesByTitle[sampleTitle];var samplesTrack=new tr.c.tracks.SampleTrack(this.viewport);samplesTrack.group=this.thread_;samplesTrack.samples=samples;samplesTrack.heading=this.thread_.userFriendlyName+': '+
+sampleTitle;samplesTrack.tooltip=this.thread_.userFriendlyDetails;samplesTrack.selectionGenerator=function(){var selection=new tr.c.Selection();for(var i=0;i<samplesTrack.samples.length;i++){selection.push(samplesTrack.samples[i]);}
 return selection;};this.appendChild(samplesTrack);},this);},collapsedDidChange:function(collapsed){if(collapsed){var h=parseInt(this.tracks[0].height);for(var i=0;i<this.tracks.length;++i){if(h>2){this.tracks[i].height=Math.floor(h)+'px';}else{this.tracks[i].style.display='none';}
-h=h*0.5;}}else{for(var i=0;i<this.tracks.length;++i){this.tracks[i].height=this.tracks[0].height;this.tracks[i].style.display='';}}}};return{ThreadTrack:ThreadTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var ObjectSnapshotView=tv.c.analysis.ObjectSnapshotView;var ObjectInstanceView=tv.c.analysis.ObjectInstanceView;var TraceModelSettings=tv.c.TraceModelSettings;var SpacingTrack=tv.c.tracks.SpacingTrack;var ProcessTrackBase=tv.b.ui.define('process-track-base',tv.c.tracks.ContainerTrack);ProcessTrackBase.prototype={__proto__:tv.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tv.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.processBase_=undefined;this.classList.add('process-track-base');this.classList.add('expanded');this.processNameEl_=tv.b.ui.createSpan();this.processNameEl_.classList.add('process-track-name');this.headerEl_=tv.b.ui.createDiv({className:'process-track-header'});this.headerEl_.appendChild(this.processNameEl_);this.headerEl_.addEventListener('click',this.onHeaderClick_.bind(this));this.appendChild(this.headerEl_);},get processBase(){return this.processBase_;},set processBase(processBase){this.processBase_=processBase;if(this.processBase_){var modelSettings=new TraceModelSettings(this.processBase_.model);var defaultValue=this.processBase_.important;this.expanded=modelSettings.getSettingFor(this.processBase_,'expanded',defaultValue);}
+h=h*0.5;}}else{for(var i=0;i<this.tracks.length;++i){this.tracks[i].height=this.tracks[0].height;this.tracks[i].style.display='';}}}};return{ThreadTrack:ThreadTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var ObjectSnapshotView=tr.c.analysis.ObjectSnapshotView;var ObjectInstanceView=tr.c.analysis.ObjectInstanceView;var SpacingTrack=tr.c.tracks.SpacingTrack;var ProcessTrackBase=tr.b.ui.define('process-track-base',tr.c.tracks.ContainerTrack);ProcessTrackBase.prototype={__proto__:tr.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tr.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.processBase_=undefined;this.classList.add('process-track-base');this.classList.add('expanded');this.processNameEl_=tr.b.ui.createSpan();this.processNameEl_.classList.add('process-track-name');this.headerEl_=tr.b.ui.createDiv({className:'process-track-header'});this.headerEl_.appendChild(this.processNameEl_);this.headerEl_.addEventListener('click',this.onHeaderClick_.bind(this));this.appendChild(this.headerEl_);},get processBase(){return this.processBase_;},set processBase(processBase){this.processBase_=processBase;if(this.processBase_){var modelSettings=new tr.model.ModelSettings(this.processBase_.model);var defaultValue=this.processBase_.important;this.expanded=modelSettings.getSettingFor(this.processBase_,'expanded',defaultValue);}
 this.updateContents_();},get expanded(){return this.classList.contains('expanded');},set expanded(expanded){expanded=!!expanded;if(this.expanded===expanded)
 return;this.classList.toggle('expanded');this.viewport_.dispatchChangeEvent();if(!this.processBase_)
-return;var modelSettings=new TraceModelSettings(this.processBase_.model);modelSettings.setSettingFor(this.processBase_,'expanded',expanded);this.updateContents_();this.viewport.rebuildEventToTrackMap();this.viewport.rebuildContainerToTrackMap();},get hasVisibleContent(){if(this.expanded)
+return;var modelSettings=new tr.model.ModelSettings(this.processBase_.model);modelSettings.setSettingFor(this.processBase_,'expanded',expanded);this.updateContents_();this.viewport.rebuildEventToTrackMap();this.viewport.rebuildContainerToTrackMap();},get hasVisibleContent(){if(this.expanded)
 return this.children.length>1;return true;},onHeaderClick_:function(e){e.stopPropagation();e.preventDefault();this.expanded=!this.expanded;},updateContents_:function(){this.tracks_.forEach(function(track){this.removeChild(track);},this);if(!this.processBase_)
 return;this.processNameEl_.textContent=this.processBase_.userFriendlyName;this.headerEl_.title=this.processBase_.userFriendlyDetails;this.willAppendTracks_();if(this.expanded){this.appendMemoryDumpTrack_();this.appendObjectInstanceTracks_();this.appendCounterTracks_();this.appendFrameTrack_();this.appendThreadTracks_();}else{this.appendSummaryTrack_();}
-this.didAppendTracks_();},addEventsToTrackMap:function(eventToTrackMap){this.tracks_.forEach(function(track){track.addEventsToTrackMap(eventToTrackMap);});},willAppendTracks_:function(){},didAppendTracks_:function(){},appendMemoryDumpTrack_:function(){},appendSummaryTrack_:function(){var track=new tv.c.tracks.ProcessSummaryTrack(this.viewport);track.process=this.process;if(!track.hasVisibleContent)
+this.didAppendTracks_();},addEventsToTrackMap:function(eventToTrackMap){this.tracks_.forEach(function(track){track.addEventsToTrackMap(eventToTrackMap);});},willAppendTracks_:function(){},didAppendTracks_:function(){},appendMemoryDumpTrack_:function(){},appendSummaryTrack_:function(){var track=new tr.c.tracks.ProcessSummaryTrack(this.viewport);track.process=this.process;if(!track.hasVisibleContent)
 return;this.appendChild(track);},appendFrameTrack_:function(){var frames=this.process?this.process.frames:undefined;if(!frames||!frames.length)
-return;var track=new tv.c.tracks.FrameTrack(this.viewport);track.frames=frames;this.appendChild(track);this.backgroundProvider=track;},appendObjectInstanceTracks_:function(){var instancesByTypeName=this.processBase_.objects.getAllInstancesByTypeName();var instanceTypeNames=tv.b.dictionaryKeys(instancesByTypeName);instanceTypeNames.sort();var didAppendAtLeastOneTrack=false;instanceTypeNames.forEach(function(typeName){var allInstances=instancesByTypeName[typeName];var instanceViewInfo=ObjectInstanceView.getTypeInfo(undefined,typeName);var snapshotViewInfo=ObjectSnapshotView.getTypeInfo(undefined,typeName);if(instanceViewInfo&&!instanceViewInfo.metadata.showInTrackView)
+return;var track=new tr.c.tracks.FrameTrack(this.viewport);track.frames=frames;this.appendChild(track);this.backgroundProvider=track;},appendObjectInstanceTracks_:function(){var instancesByTypeName=this.processBase_.objects.getAllInstancesByTypeName();var instanceTypeNames=tr.b.dictionaryKeys(instancesByTypeName);instanceTypeNames.sort();var didAppendAtLeastOneTrack=false;instanceTypeNames.forEach(function(typeName){var allInstances=instancesByTypeName[typeName];var instanceViewInfo=ObjectInstanceView.getTypeInfo(undefined,typeName);var snapshotViewInfo=ObjectSnapshotView.getTypeInfo(undefined,typeName);if(instanceViewInfo&&!instanceViewInfo.metadata.showInTrackView)
 instanceViewInfo=undefined;if(snapshotViewInfo&&!snapshotViewInfo.metadata.showInTrackView)
 snapshotViewInfo=undefined;var hasViewInfo=instanceViewInfo||snapshotViewInfo;var visibleInstances=[];for(var i=0;i<allInstances.length;i++){var instance=allInstances[i];if(instance.snapshots.length===0)
 continue;if(instance.hasImplicitSnapshots&&!hasViewInfo)
 continue;visibleInstances.push(instance);}
 if(visibleInstances.length===0)
-return;var trackConstructor=tv.c.tracks.ObjectInstanceTrack.getConstructor(undefined,typeName);if(!trackConstructor){var snapshotViewInfo=ObjectSnapshotView.getTypeInfo(undefined,typeName);if(snapshotViewInfo&&snapshotViewInfo.metadata.showInstances){trackConstructor=tv.c.tracks.ObjectInstanceGroupTrack;}else{trackConstructor=tv.c.tracks.ObjectInstanceTrack;}}
+return;var trackConstructor=tr.c.tracks.ObjectInstanceTrack.getConstructor(undefined,typeName);if(!trackConstructor){var snapshotViewInfo=ObjectSnapshotView.getTypeInfo(undefined,typeName);if(snapshotViewInfo&&snapshotViewInfo.metadata.showInstances){trackConstructor=tr.c.tracks.ObjectInstanceGroupTrack;}else{trackConstructor=tr.c.tracks.ObjectInstanceTrack;}}
 var track=new trackConstructor(this.viewport);track.objectInstances=visibleInstances;this.appendChild(track);didAppendAtLeastOneTrack=true;},this);if(didAppendAtLeastOneTrack)
-this.appendChild(new SpacingTrack(this.viewport));},appendCounterTracks_:function(){var counters=tv.b.dictionaryValues(this.processBase.counters);counters.sort(tv.c.trace_model.Counter.compare);counters.forEach(function(counter){var track=new tv.c.tracks.CounterTrack(this.viewport);track.counter=counter;this.appendChild(track);this.appendChild(new SpacingTrack(this.viewport));}.bind(this));},appendThreadTracks_:function(){var threads=tv.b.dictionaryValues(this.processBase.threads);threads.sort(tv.c.trace_model.Thread.compare);threads.forEach(function(thread){var track=new tv.c.tracks.ThreadTrack(this.viewport);track.thread=thread;if(!track.hasVisibleContent)
-return;this.appendChild(track);this.appendChild(new SpacingTrack(this.viewport));}.bind(this));}};return{ProcessTrackBase:ProcessTrackBase};});'use strict';tv.exportTo('tv.c.tracks',function(){var CpuTrack=tv.b.ui.define('cpu-track',tv.c.tracks.ContainerTrack);CpuTrack.prototype={__proto__:tv.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tv.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.classList.add('cpu-track');this.detailedMode_=true;},get cpu(){return this.cpu_;},set cpu(cpu){this.cpu_=cpu;this.updateContents_();},get detailedMode(){return this.detailedMode_;},set detailedMode(detailedMode){this.detailedMode_=detailedMode;this.updateContents_();},get tooltip(){return this.tooltip_;},set tooltip(value){this.tooltip_=value;this.updateContents_();},get hasVisibleContent(){if(this.cpu_===undefined)
+this.appendChild(new SpacingTrack(this.viewport));},appendCounterTracks_:function(){var counters=tr.b.dictionaryValues(this.processBase.counters);counters.sort(tr.model.Counter.compare);counters.forEach(function(counter){var track=new tr.c.tracks.CounterTrack(this.viewport);track.counter=counter;this.appendChild(track);this.appendChild(new SpacingTrack(this.viewport));}.bind(this));},appendThreadTracks_:function(){var threads=tr.b.dictionaryValues(this.processBase.threads);threads.sort(tr.model.Thread.compare);threads.forEach(function(thread){var track=new tr.c.tracks.ThreadTrack(this.viewport);track.thread=thread;if(!track.hasVisibleContent)
+return;this.appendChild(track);this.appendChild(new SpacingTrack(this.viewport));}.bind(this));}};return{ProcessTrackBase:ProcessTrackBase};});'use strict';tr.exportTo('tr.c.tracks',function(){var CpuTrack=tr.b.ui.define('cpu-track',tr.c.tracks.ContainerTrack);CpuTrack.prototype={__proto__:tr.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tr.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.classList.add('cpu-track');this.detailedMode_=true;},get cpu(){return this.cpu_;},set cpu(cpu){this.cpu_=cpu;this.updateContents_();},get detailedMode(){return this.detailedMode_;},set detailedMode(detailedMode){this.detailedMode_=detailedMode;this.updateContents_();},get tooltip(){return this.tooltip_;},set tooltip(value){this.tooltip_=value;this.updateContents_();},get hasVisibleContent(){if(this.cpu_===undefined)
 return false;var cpu=this.cpu_;if(cpu.slices.length)
 return true;if(cpu.samples&&cpu.samples.length)
-return true;if(tv.b.dictionaryLength(cpu.counters)>0)
+return true;if(tr.b.dictionaryLength(cpu.counters)>0)
 return true;return false;},updateContents_:function(){this.detach();if(!this.cpu_)
-return;var slices=this.cpu_.slices;if(slices.length){var track=new tv.c.tracks.SliceTrack(this.viewport);track.slices=slices;track.heading=this.cpu_.userFriendlyName+':';this.appendChild(track);}
-if(this.detailedMode_){this.appendSamplesTracks_();for(var counterName in this.cpu_.counters){var counter=this.cpu_.counters[counterName];track=new tv.c.tracks.CounterTrack(this.viewport);track.heading=this.cpu_.userFriendlyName+' '+
+return;var slices=this.cpu_.slices;if(slices.length){var track=new tr.c.tracks.SliceTrack(this.viewport);track.slices=slices;track.heading=this.cpu_.userFriendlyName+':';this.appendChild(track);}
+if(this.detailedMode_){this.appendSamplesTracks_();for(var counterName in this.cpu_.counters){var counter=this.cpu_.counters[counterName];track=new tr.c.tracks.CounterTrack(this.viewport);track.heading=this.cpu_.userFriendlyName+' '+
 counter.name+':';track.counter=counter;this.appendChild(track);}}},appendSamplesTracks_:function(){var samples=this.cpu_.samples;if(samples===undefined||samples.length===0)
 return;var samplesByTitle={};samples.forEach(function(sample){if(samplesByTitle[sample.title]===undefined)
-samplesByTitle[sample.title]=[];samplesByTitle[sample.title].push(sample);});var sampleTitles=tv.b.dictionaryKeys(samplesByTitle);sampleTitles.sort();sampleTitles.forEach(function(sampleTitle){var samples=samplesByTitle[sampleTitle];var samplesTrack=new tv.c.tracks.SliceTrack(this.viewport);samplesTrack.group=this.cpu_;samplesTrack.slices=samples;samplesTrack.heading=this.cpu_.userFriendlyName+': '+
-sampleTitle;samplesTrack.tooltip=this.cpu_.userFriendlyDetails;samplesTrack.selectionGenerator=function(){var selection=new tv.c.Selection();for(var i=0;i<samplesTrack.slices.length;i++){selection.push(samplesTrack.slices[i]);}
-return selection;};this.appendChild(samplesTrack);},this);}};return{CpuTrack:CpuTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var Cpu=tv.c.trace_model.Cpu;var CpuTrack=tv.c.tracks.cpu_track;var ProcessTrackBase=tv.c.tracks.ProcessTrackBase;var SpacingTrack=tv.c.tracks.SpacingTrack;var KernelTrack=tv.b.ui.define('kernel-track',ProcessTrackBase);KernelTrack.prototype={__proto__:ProcessTrackBase.prototype,decorate:function(viewport){tv.c.tracks.ProcessTrackBase.prototype.decorate.call(this,viewport);},set kernel(kernel){this.processBase=kernel;},get kernel(){return this.processBase;},get eventContainer(){return this.kernel;},get hasVisibleContent(){return this.children.length>1;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.kernel,this);},willAppendTracks_:function(){var cpus=tv.b.dictionaryValues(this.kernel.cpus);cpus.sort(tv.c.trace_model.Cpu.compare);var didAppendAtLeastOneTrack=false;for(var i=0;i<cpus.length;++i){var cpu=cpus[i];var track=new tv.c.tracks.CpuTrack(this.viewport);track.detailedMode=this.expanded;track.cpu=cpu;if(!track.hasVisibleContent)
+samplesByTitle[sample.title]=[];samplesByTitle[sample.title].push(sample);});var sampleTitles=tr.b.dictionaryKeys(samplesByTitle);sampleTitles.sort();sampleTitles.forEach(function(sampleTitle){var samples=samplesByTitle[sampleTitle];var samplesTrack=new tr.c.tracks.SliceTrack(this.viewport);samplesTrack.group=this.cpu_;samplesTrack.slices=samples;samplesTrack.heading=this.cpu_.userFriendlyName+': '+
+sampleTitle;samplesTrack.tooltip=this.cpu_.userFriendlyDetails;samplesTrack.selectionGenerator=function(){var selection=new tr.c.Selection();for(var i=0;i<samplesTrack.slices.length;i++){selection.push(samplesTrack.slices[i]);}
+return selection;};this.appendChild(samplesTrack);},this);}};return{CpuTrack:CpuTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var Cpu=tr.model.Cpu;var CpuTrack=tr.c.tracks.cpu_track;var ProcessTrackBase=tr.c.tracks.ProcessTrackBase;var SpacingTrack=tr.c.tracks.SpacingTrack;var KernelTrack=tr.b.ui.define('kernel-track',ProcessTrackBase);KernelTrack.prototype={__proto__:ProcessTrackBase.prototype,decorate:function(viewport){ProcessTrackBase.prototype.decorate.call(this,viewport);},set kernel(kernel){this.processBase=kernel;},get kernel(){return this.processBase;},get eventContainer(){return this.kernel;},get hasVisibleContent(){return this.children.length>1;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.kernel,this);},willAppendTracks_:function(){var cpus=tr.b.dictionaryValues(this.kernel.cpus);cpus.sort(tr.model.Cpu.compare);var didAppendAtLeastOneTrack=false;for(var i=0;i<cpus.length;++i){var cpu=cpus[i];var track=new tr.c.tracks.CpuTrack(this.viewport);track.detailedMode=this.expanded;track.cpu=cpu;if(!track.hasVisibleContent)
 continue;this.appendChild(track);didAppendAtLeastOneTrack=true;}
 if(didAppendAtLeastOneTrack)
-this.appendChild(new SpacingTrack(this.viewport));}};return{KernelTrack:KernelTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var AlertTrack=tv.b.ui.define('alert-track',tv.c.tracks.LetterDotTrack);AlertTrack.prototype={__proto__:tv.c.tracks.LetterDotTrack.prototype,decorate:function(viewport){tv.c.tracks.LetterDotTrack.prototype.decorate.call(this,viewport);this.heading='Alerts';this.alerts_=undefined;},get alerts(){return this.alerts_;},set alerts(alerts){this.alerts_=alerts;if(alerts===undefined){this.items=undefined;return;}
-this.items=this.alerts_.map(function(alert){return new tv.c.tracks.LetterDot(alert,String.fromCharCode(9888),alert.colorId,alert.start);});}};return{AlertTrack:AlertTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var ALLOCATOR_SIZE_ATTRIBUTE_NAME='outer_size';function addDictionary(dstDict,srcDict){tv.b.iterItems(srcDict,function(key,value){var existingValue=dstDict[key];if(existingValue===undefined)
+this.appendChild(new SpacingTrack(this.viewport));}};return{KernelTrack:KernelTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var AlertTrack=tr.b.ui.define('alert-track',tr.c.tracks.LetterDotTrack);AlertTrack.prototype={__proto__:tr.c.tracks.LetterDotTrack.prototype,decorate:function(viewport){tr.c.tracks.LetterDotTrack.prototype.decorate.call(this,viewport);this.heading='Alerts';this.alerts_=undefined;},get alerts(){return this.alerts_;},set alerts(alerts){this.alerts_=alerts;if(alerts===undefined){this.items=undefined;return;}
+this.items=this.alerts_.map(function(alert){return new tr.c.tracks.LetterDot(alert,String.fromCharCode(9888),alert.colorId,alert.start);});}};return{AlertTrack:AlertTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var ALLOCATOR_SIZE_ATTRIBUTE_OLD_NAME='outer_size';var ALLOCATOR_SIZE_ATTRIBUTE_NAME='size';function addDictionary(dstDict,srcDict){tr.b.iterItems(srcDict,function(key,value){var existingValue=dstDict[key];if(existingValue===undefined)
 existingValue=0;dstDict[key]=existingValue+value;});}
 function getProcessMemoryDumpAllocatorSizes(processMemoryDump){var allocatorDumps=processMemoryDump.memoryAllocatorDumps;if(allocatorDumps===undefined)
-return{};var allocatorSizes={};allocatorDumps.forEach(function(allocatorDump){var allocatorSize=allocatorDump.attributes[ALLOCATOR_SIZE_ATTRIBUTE_NAME];if(allocatorSize===undefined)
+return{};var allocatorSizes={};allocatorDumps.forEach(function(allocatorDump){if(allocatorDump.fullName==='tracing')
+return;var allocatorSize=allocatorDump.attributes[ALLOCATOR_SIZE_ATTRIBUTE_NAME];if(allocatorSize===undefined){allocatorSize=allocatorDump.attributes[ALLOCATOR_SIZE_ATTRIBUTE_OLD_NAME];}
+if(allocatorSize===undefined)
 return;var allocatorSizeValue=allocatorSize.value;if(allocatorSizeValue===undefined)
-return;allocatorSizes[allocatorDump.fullName]=allocatorSizeValue;});return allocatorSizes;};function getGlobalMemoryDumpAllocatorSizes(globalMemoryDump){var globalAllocatorSizes={};tv.b.iterItems(globalMemoryDump.processMemoryDumps,function(pid,processMemoryDump){addDictionary(globalAllocatorSizes,getProcessMemoryDumpAllocatorSizes(processMemoryDump));});return globalAllocatorSizes;}
-function buildAllocatedMemoryChartSeries(memoryDumps,memoryDumpToAllocatorSizesFn){var allocatorNameToPoints={};var dumpsData=memoryDumps.map(function(memoryDump){var allocatorSizes=memoryDumpToAllocatorSizesFn(memoryDump);tv.b.iterItems(allocatorSizes,function(allocatorName){allocatorNameToPoints[allocatorName]=[];});return{dump:memoryDump,sizes:allocatorSizes};});if(Object.keys(allocatorNameToPoints).length===0)
-return undefined;dumpsData.forEach(function(dumpData){var memoryDump=dumpData.dump;var allocatorSizes=dumpData.sizes;tv.b.iterItems(allocatorNameToPoints,function(allocatorName,points){var allocatorSize=allocatorSizes[allocatorName]||0;points.push(new tv.c.tracks.ChartPoint(memoryDump,memoryDump.start,allocatorSize));});});var axis=new tv.c.tracks.ChartAxis(0);var series=[];tv.b.iterItems(allocatorNameToPoints,function(allocatorName,points){var colorId=tv.b.ui.getColorIdForGeneralPurposeString(allocatorName);var renderingConfig={chartType:tv.c.tracks.ChartSeriesType.LINE,colorId:colorId};series.push(new tv.c.tracks.ChartSeries(points,axis,renderingConfig));});return series;}
-function buildMemoryLetterDots(memoryDumps){var memoryColorId=tv.b.ui.getColorIdForReservedName('memory_dump');return memoryDumps.map(function(memoryDump){return new tv.c.tracks.LetterDot(memoryDump,'M',memoryColorId,memoryDump.start);});}
+return;allocatorSizes[allocatorDump.fullName]=allocatorSizeValue;});return allocatorSizes;};function getGlobalMemoryDumpAllocatorSizes(globalMemoryDump){var globalAllocatorSizes={};tr.b.iterItems(globalMemoryDump.processMemoryDumps,function(pid,processMemoryDump){addDictionary(globalAllocatorSizes,getProcessMemoryDumpAllocatorSizes(processMemoryDump));});return globalAllocatorSizes;}
+function buildAllocatedMemoryChartSeries(memoryDumps,memoryDumpToAllocatorSizesFn){var allocatorNameToPoints={};var dumpsData=memoryDumps.map(function(memoryDump){var allocatorSizes=memoryDumpToAllocatorSizesFn(memoryDump);tr.b.iterItems(allocatorSizes,function(allocatorName){allocatorNameToPoints[allocatorName]=[];});return{dump:memoryDump,sizes:allocatorSizes};});if(Object.keys(allocatorNameToPoints).length===0)
+return undefined;dumpsData.forEach(function(dumpData){var memoryDump=dumpData.dump;var allocatorSizes=dumpData.sizes;tr.b.iterItems(allocatorNameToPoints,function(allocatorName,points){var allocatorSize=allocatorSizes[allocatorName]||0;points.push(new tr.c.tracks.ChartPoint(memoryDump,memoryDump.start,allocatorSize));});});var axis=new tr.c.tracks.ChartAxis(0);var series=[];tr.b.iterItems(allocatorNameToPoints,function(allocatorName,points){var colorId=tr.b.ui.getColorIdForGeneralPurposeString(allocatorName);var renderingConfig={chartType:tr.c.tracks.ChartSeriesType.LINE,colorId:colorId};series.push(new tr.c.tracks.ChartSeries(points,axis,renderingConfig));});return series;}
+function buildMemoryLetterDots(memoryDumps){var memoryColorId=tr.b.ui.getColorIdForReservedName('memory_dump');return memoryDumps.map(function(memoryDump){return new tr.c.tracks.LetterDot(memoryDump,'M',memoryColorId,memoryDump.start);});}
 function buildGlobalUsedMemoryChartSeries(globalMemoryDumps){var containsVmRegions=globalMemoryDumps.some(function(globalDump){for(var pid in globalDump.processMemoryDumps)
 if(globalDump.processMemoryDumps[pid].mostRecentVmRegions)
 return true;return false;});if(!containsVmRegions)
-return undefined;var pidToProcess={};globalMemoryDumps.forEach(function(globalDump){tv.b.iterItems(globalDump.processMemoryDumps,function(pid,processDump){pidToProcess[pid]=processDump.process;});});var pidToPoints={};tv.b.iterItems(pidToProcess,function(pid,process){pidToPoints[pid]=[];});globalMemoryDumps.forEach(function(globalDump){var pssBase=0;tv.b.iterItems(pidToPoints,function(pid,points){var processMemoryDump=globalDump.processMemoryDumps[pid];var pss;if(processMemoryDump===undefined){pss=0;}else{pss=processMemoryDump.mostRecentTotalProportionalResidentSizeInBytes;if(pss===undefined){pss=0;}}
-var cumulativePss=pssBase+pss;points.push(new tv.c.tracks.ChartPoint(globalDump,globalDump.start,cumulativePss,pssBase));pssBase=cumulativePss;});});var axis=new tv.c.tracks.ChartAxis(0);var series=[];tv.b.iterItems(pidToPoints,function(pid,points){var process=pidToProcess[pid];var colorId=tv.b.ui.getColorIdForGeneralPurposeString(process.userFriendlyName);var renderingConfig={chartType:tv.c.tracks.ChartSeriesType.AREA,colorId:colorId,backgroundOpacity:0.8};series.push(new tv.c.tracks.ChartSeries(points,axis,renderingConfig));});series.reverse();return series;}
+return undefined;var pidToProcess={};globalMemoryDumps.forEach(function(globalDump){tr.b.iterItems(globalDump.processMemoryDumps,function(pid,processDump){pidToProcess[pid]=processDump.process;});});var pidToPoints={};tr.b.iterItems(pidToProcess,function(pid,process){pidToPoints[pid]=[];});globalMemoryDumps.forEach(function(globalDump){var pssBase=0;tr.b.iterItems(pidToPoints,function(pid,points){var processMemoryDump=globalDump.processMemoryDumps[pid];var pss;if(processMemoryDump===undefined){pss=0;}else{pss=processMemoryDump.getMostRecentTotalVmRegionStat('proportionalResident');if(pss===undefined){pss=0;}}
+var cumulativePss=pssBase+pss;points.push(new tr.c.tracks.ChartPoint(globalDump,globalDump.start,cumulativePss,pssBase));pssBase=cumulativePss;});});var axis=new tr.c.tracks.ChartAxis(0);var series=[];tr.b.iterItems(pidToPoints,function(pid,points){var process=pidToProcess[pid];var colorId=tr.b.ui.getColorIdForGeneralPurposeString(process.userFriendlyName);var renderingConfig={chartType:tr.c.tracks.ChartSeriesType.AREA,colorId:colorId,backgroundOpacity:0.8};series.push(new tr.c.tracks.ChartSeries(points,axis,renderingConfig));});series.reverse();return series;}
 function buildProcessAllocatedMemoryChartSeries(processMemoryDumps){return buildAllocatedMemoryChartSeries(processMemoryDumps,getProcessMemoryDumpAllocatorSizes);}
 function buildGlobalAllocatedMemoryChartSeries(globalMemoryDumps){return buildAllocatedMemoryChartSeries(globalMemoryDumps,getGlobalMemoryDumpAllocatorSizes);}
-return{buildMemoryLetterDots:buildMemoryLetterDots,buildGlobalUsedMemoryChartSeries:buildGlobalUsedMemoryChartSeries,buildProcessAllocatedMemoryChartSeries:buildProcessAllocatedMemoryChartSeries,buildGlobalAllocatedMemoryChartSeries:buildGlobalAllocatedMemoryChartSeries};});'use strict';tv.exportTo('tv.c.tracks',function(){var USED_MEMORY_TRACK_HEIGHT=50;var ALLOCATED_MEMORY_TRACK_HEIGHT=50;var GlobalMemoryDumpTrack=tv.b.ui.define('global-memory-dump-track',tv.c.tracks.ContainerTrack);GlobalMemoryDumpTrack.prototype={__proto__:tv.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tv.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.memoryDumps_=undefined;},get memoryDumps(){return this.memoryDumps_;},set memoryDumps(memoryDumps){this.memoryDumps_=memoryDumps;this.updateContents_();},updateContents_:function(){this.tracks_.forEach(function(track){this.removeChild(track);},this);if(!this.memoryDumps_||!this.memoryDumps_.length)
-return;this.appendDumpDotsTrack_();this.appendUsedMemoryTrack_();this.appendAllocatedMemoryTrack_();},appendDumpDotsTrack_:function(){var items=tv.c.tracks.buildMemoryLetterDots(this.memoryDumps_);if(!items)
-return;var track=new tv.c.tracks.LetterDotTrack(this.viewport);track.heading='Memory Dumps';track.items=items;this.appendChild(track);},appendUsedMemoryTrack_:function(){var series=tv.c.tracks.buildGlobalUsedMemoryChartSeries(this.memoryDumps_);if(!series)
-return;var track=new tv.c.tracks.ChartTrack(this.viewport);track.heading='Used memory (per process)';track.height=USED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});this.appendChild(track);},appendAllocatedMemoryTrack_:function(){var series=tv.c.tracks.buildGlobalAllocatedMemoryChartSeries(this.memoryDumps_);if(!series)
-return;var track=new tv.c.tracks.ChartTrack(this.viewport);track.heading='Allocated memory (per allocator)';track.height=ALLOCATED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});this.appendChild(track);}};return{GlobalMemoryDumpTrack:GlobalMemoryDumpTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var ALLOCATED_MEMORY_TRACK_HEIGHT=50;var ProcessMemoryDumpTrack=tv.b.ui.define('process-memory-dump-track',tv.c.tracks.ContainerTrack);ProcessMemoryDumpTrack.prototype={__proto__:tv.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tv.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.memoryDumps_=undefined;},get memoryDumps(){return this.memoryDumps_;},set memoryDumps(memoryDumps){this.memoryDumps_=memoryDumps;this.updateContents_();},updateContents_:function(){this.tracks_.forEach(function(track){this.removeChild(track);},this);if(!this.memoryDumps_||!this.memoryDumps_.length)
-return;this.appendAllocatedMemoryTrack_();},appendAllocatedMemoryTrack_:function(){var series=tv.c.tracks.buildProcessAllocatedMemoryChartSeries(this.memoryDumps_);if(!series)
-return;var track=new tv.c.tracks.ChartTrack(this.viewport);track.heading='Allocated memory (per allocator)';track.height=ALLOCATED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});this.appendChild(track);}};return{ProcessMemoryDumpTrack:ProcessMemoryDumpTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var ProcessTrackBase=tv.c.tracks.ProcessTrackBase;var ProcessTrack=tv.b.ui.define('process-track',ProcessTrackBase);ProcessTrack.prototype={__proto__:ProcessTrackBase.prototype,decorate:function(viewport){tv.c.tracks.ProcessTrackBase.prototype.decorate.call(this,viewport);},drawTrack:function(type){switch(type){case tv.c.tracks.DrawType.INSTANT_EVENT:if(!this.processBase.instantEvents||this.processBase.instantEvents.length===0)
-break;var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));var dt=this.viewport.currentDisplayTransform;var viewLWorld=dt.xViewToWorld(0);var viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);tv.c.drawInstantSlicesAsLines(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.processBase.instantEvents,2);ctx.restore();break;case tv.c.tracks.DrawType.BACKGROUND:this.drawBackground_();return;}
-tv.c.tracks.ContainerTrack.prototype.drawTrack.call(this,type);},drawBackground_:function(){var ctx=this.context();var canvasBounds=ctx.canvas.getBoundingClientRect();var pixelRatio=window.devicePixelRatio||1;var draw=false;ctx.fillStyle='#eee';for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tv.c.tracks.Track)||(this.children[i]instanceof tv.c.tracks.SpacingTrack))
+return{buildMemoryLetterDots:buildMemoryLetterDots,buildGlobalUsedMemoryChartSeries:buildGlobalUsedMemoryChartSeries,buildProcessAllocatedMemoryChartSeries:buildProcessAllocatedMemoryChartSeries,buildGlobalAllocatedMemoryChartSeries:buildGlobalAllocatedMemoryChartSeries};});'use strict';tr.exportTo('tr.c.tracks',function(){var USED_MEMORY_TRACK_HEIGHT=50;var ALLOCATED_MEMORY_TRACK_HEIGHT=50;var GlobalMemoryDumpTrack=tr.b.ui.define('global-memory-dump-track',tr.c.tracks.ContainerTrack);GlobalMemoryDumpTrack.prototype={__proto__:tr.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tr.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.memoryDumps_=undefined;},get memoryDumps(){return this.memoryDumps_;},set memoryDumps(memoryDumps){this.memoryDumps_=memoryDumps;this.updateContents_();},updateContents_:function(){this.tracks_.forEach(function(track){this.removeChild(track);},this);if(!this.memoryDumps_||!this.memoryDumps_.length)
+return;this.appendDumpDotsTrack_();this.appendUsedMemoryTrack_();this.appendAllocatedMemoryTrack_();},appendDumpDotsTrack_:function(){var items=tr.c.tracks.buildMemoryLetterDots(this.memoryDumps_);if(!items)
+return;var track=new tr.c.tracks.LetterDotTrack(this.viewport);track.heading='Memory Dumps';track.items=items;this.appendChild(track);},appendUsedMemoryTrack_:function(){var series=tr.c.tracks.buildGlobalUsedMemoryChartSeries(this.memoryDumps_);if(!series)
+return;var track=new tr.c.tracks.ChartTrack(this.viewport);track.heading='Used memory (per process)';track.height=USED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});this.appendChild(track);},appendAllocatedMemoryTrack_:function(){var series=tr.c.tracks.buildGlobalAllocatedMemoryChartSeries(this.memoryDumps_);if(!series)
+return;var track=new tr.c.tracks.ChartTrack(this.viewport);track.heading='Allocated memory (per allocator)';track.height=ALLOCATED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});this.appendChild(track);}};return{GlobalMemoryDumpTrack:GlobalMemoryDumpTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var ALLOCATED_MEMORY_TRACK_HEIGHT=50;var ProcessMemoryDumpTrack=tr.b.ui.define('process-memory-dump-track',tr.c.tracks.ContainerTrack);ProcessMemoryDumpTrack.prototype={__proto__:tr.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tr.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.memoryDumps_=undefined;},get memoryDumps(){return this.memoryDumps_;},set memoryDumps(memoryDumps){this.memoryDumps_=memoryDumps;this.updateContents_();},updateContents_:function(){this.tracks_.forEach(function(track){this.removeChild(track);},this);if(!this.memoryDumps_||!this.memoryDumps_.length)
+return;this.appendAllocatedMemoryTrack_();},appendAllocatedMemoryTrack_:function(){var series=tr.c.tracks.buildProcessAllocatedMemoryChartSeries(this.memoryDumps_);if(!series)
+return;var track=new tr.c.tracks.ChartTrack(this.viewport);track.heading='Allocated memory (per allocator)';track.height=ALLOCATED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});this.appendChild(track);}};return{ProcessMemoryDumpTrack:ProcessMemoryDumpTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var ProcessTrackBase=tr.c.tracks.ProcessTrackBase;var ProcessTrack=tr.b.ui.define('process-track',ProcessTrackBase);ProcessTrack.prototype={__proto__:ProcessTrackBase.prototype,decorate:function(viewport){tr.c.tracks.ProcessTrackBase.prototype.decorate.call(this,viewport);},drawTrack:function(type){switch(type){case tr.c.tracks.DrawType.INSTANT_EVENT:if(!this.processBase.instantEvents||this.processBase.instantEvents.length===0)
+break;var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));var dt=this.viewport.currentDisplayTransform;var viewLWorld=dt.xViewToWorld(0);var viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);tr.c.drawInstantSlicesAsLines(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.processBase.instantEvents,2);ctx.restore();break;case tr.c.tracks.DrawType.BACKGROUND:this.drawBackground_();return;}
+tr.c.tracks.ContainerTrack.prototype.drawTrack.call(this,type);},drawBackground_:function(){var ctx=this.context();var canvasBounds=ctx.canvas.getBoundingClientRect();var pixelRatio=window.devicePixelRatio||1;var draw=false;ctx.fillStyle='#eee';for(var i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.c.tracks.Track)||(this.children[i]instanceof tr.c.tracks.SpacingTrack))
 continue;draw=!draw;if(!draw)
-continue;var bounds=this.children[i].getBoundingClientRect();ctx.fillRect(0,pixelRatio*(bounds.top-canvasBounds.top),ctx.canvas.width,pixelRatio*bounds.height);}},set process(process){this.processBase=process;},get process(){return this.processBase;},get eventContainer(){return this.process;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.process,this);this.tracks_.forEach(function(track){track.addContainersToTrackMap(containerToTrackMap);});},appendMemoryDumpTrack_:function(){var processMemoryDumps=this.process.memoryDumps;if(processMemoryDumps.length){var pmdt=new tv.c.tracks.ProcessMemoryDumpTrack(this.viewport_);pmdt.memoryDumps=processMemoryDumps;this.appendChild(pmdt);}},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){function onPickHit(instantEvent){selection.push(instantEvent);}
-tv.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,function(x){return x.start;},function(x){return x.duration;},loWX,hiWX,onPickHit.bind(this));tv.c.tracks.ContainerTrack.prototype.addIntersectingEventsInRangeToSelectionInWorldSpace.apply(this,arguments);},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){this.addClosestInstantEventToSelection(this.processBase.instantEvents,worldX,worldMaxDist,selection);tv.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.apply(this,arguments);}};return{ProcessTrack:ProcessTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){function HackyMultiRowTrack(viewport,model){var mrt=new tv.c.tracks.MultiRowTrack(viewport);mrt.heading='Interactions';mrt.buildSubRows_=function(slices){slices.sort(function(x,y){var r=x.title.localeCompare(y.title);if(r)
-return r;return x.start-y.start;});return tv.c.tracks.AsyncSliceGroupTrack.prototype.buildSubRows_.call({},slices,true);};mrt.addSubTrack_=function(slices){var track=new tv.c.tracks.SliceTrack(this.viewport);track.slices=slices;this.appendChild(track);return track;};mrt.setItemsToGroup(model.interaction_records,{guid:tv.b.GUID.allocate(),model:model,getSettingsKey:function(){return undefined;}});return mrt;}
-var SelectionState=tv.c.trace_model.SelectionState;var EventPresenter=tv.c.EventPresenter;var TraceModelTrack=tv.b.ui.define('trace-model-track',tv.c.tracks.ContainerTrack);TraceModelTrack.prototype={__proto__:tv.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tv.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.classList.add('model-track');var typeInfos=tv.c.tracks.Highlighter.getAllRegisteredTypeInfos();this.highlighters_=typeInfos.map(function(typeInfo){return new typeInfo.constructor(viewport);});this.upperMode_=false;this.annotationViews_=[];},get upperMode(){return this.upperMode_;},set upperMode(upperMode){this.upperMode_=upperMode;this.updateContents_();},detach:function(){tv.c.tracks.ContainerTrack.prototype.detach.call(this);},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();this.model_.addEventListener('annotationChange',this.updateAnnotations_.bind(this));},get hasVisibleContent(){return this.children.length>0;},updateContents_:function(){this.textContent='';if(!this.model_)
+continue;var bounds=this.children[i].getBoundingClientRect();ctx.fillRect(0,pixelRatio*(bounds.top-canvasBounds.top),ctx.canvas.width,pixelRatio*bounds.height);}},set process(process){this.processBase=process;},get process(){return this.processBase;},get eventContainer(){return this.process;},addContainersToTrackMap:function(containerToTrackMap){containerToTrackMap.addContainer(this.process,this);this.tracks_.forEach(function(track){track.addContainersToTrackMap(containerToTrackMap);});},appendMemoryDumpTrack_:function(){var processMemoryDumps=this.process.memoryDumps;if(processMemoryDumps.length){var pmdt=new tr.c.tracks.ProcessMemoryDumpTrack(this.viewport_);pmdt.memoryDumps=processMemoryDumps;this.appendChild(pmdt);}},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){function onPickHit(instantEvent){selection.push(instantEvent);}
+tr.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,function(x){return x.start;},function(x){return x.duration;},loWX,hiWX,onPickHit.bind(this));tr.c.tracks.ContainerTrack.prototype.addIntersectingEventsInRangeToSelectionInWorldSpace.apply(this,arguments);},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){this.addClosestInstantEventToSelection(this.processBase.instantEvents,worldX,worldMaxDist,selection);tr.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.apply(this,arguments);}};return{ProcessTrack:ProcessTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){function HackyMultiRowTrack(viewport,model){var mrt=new tr.c.tracks.MultiRowTrack(viewport);mrt.heading='Interactions';mrt.buildSubRows_=function(slices){slices.sort(function(x,y){var r=x.title.localeCompare(y.title);if(r)
+return r;return x.start-y.start;});return tr.c.tracks.AsyncSliceGroupTrack.prototype.buildSubRows_.call({},slices,true);};mrt.addSubTrack_=function(slices){var track=new tr.c.tracks.SliceTrack(this.viewport);track.slices=slices;this.appendChild(track);return track;};mrt.setItemsToGroup(model.interaction_records,{guid:tr.b.GUID.allocate(),model:model,getSettingsKey:function(){return undefined;}});return mrt;}
+var SelectionState=tr.model.SelectionState;var EventPresenter=tr.c.EventPresenter;var ModelTrack=tr.b.ui.define('model-track',tr.c.tracks.ContainerTrack);ModelTrack.prototype={__proto__:tr.c.tracks.ContainerTrack.prototype,decorate:function(viewport){tr.c.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.classList.add('model-track');var typeInfos=tr.c.tracks.Highlighter.getAllRegisteredTypeInfos();this.highlighters_=typeInfos.map(function(typeInfo){return new typeInfo.constructor(viewport);});this.upperMode_=false;this.annotationViews_=[];},get upperMode(){return this.upperMode_;},set upperMode(upperMode){this.upperMode_=upperMode;this.updateContents_();},detach:function(){tr.c.tracks.ContainerTrack.prototype.detach.call(this);},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();this.model_.addEventListener('annotationChange',this.updateAnnotations_.bind(this));},get hasVisibleContent(){return this.children.length>0;},updateContents_:function(){this.textContent='';if(!this.model_)
 return;if(this.upperMode_)
 this.updateContentsForUpperMode_();else
 this.updateContentsForLowerMode_();},updateContentsForUpperMode_:function(){},updateContentsForLowerMode_:function(){if(this.model_.interaction_records.length){var mrt=new HackyMultiRowTrack(this.viewport_,this.model_);this.appendChild(mrt);}
-if(this.model_.alerts.length){var at=new tv.c.tracks.AlertTrack(this.viewport_);at.alerts=this.model_.alerts;this.appendChild(at);}
-if(this.model_.globalMemoryDumps.length){var gmdt=new tv.c.tracks.GlobalMemoryDumpTrack(this.viewport_);gmdt.memoryDumps=this.model_.globalMemoryDumps;this.appendChild(gmdt);}
-this.appendKernelTrack_();var processes=this.model_.getAllProcesses();processes.sort(tv.c.trace_model.Process.compare);for(var i=0;i<processes.length;++i){var process=processes[i];var track=new tv.c.tracks.ProcessTrack(this.viewport);track.process=process;if(!track.hasVisibleContent)
+if(this.model_.alerts.length){var at=new tr.c.tracks.AlertTrack(this.viewport_);at.alerts=this.model_.alerts;this.appendChild(at);}
+if(this.model_.globalMemoryDumps.length){var gmdt=new tr.c.tracks.GlobalMemoryDumpTrack(this.viewport_);gmdt.memoryDumps=this.model_.globalMemoryDumps;this.appendChild(gmdt);}
+this.appendKernelTrack_();var processes=this.model_.getAllProcesses();processes.sort(tr.model.Process.compare);for(var i=0;i<processes.length;++i){var process=processes[i];var track=new tr.c.tracks.ProcessTrack(this.viewport);track.process=process;if(!track.hasVisibleContent)
 continue;this.appendChild(track);}
 this.viewport_.rebuildEventToTrackMap();this.viewport_.rebuildContainerToTrackMap();for(var i=0;i<this.highlighters_.length;i++){this.highlighters_[i].processModel(this.model_);}
 this.updateAnnotations_();},updateAnnotations_:function(){this.annotationViews_=[];var annotations=this.model_.getAllAnnotations();for(var i=0;i<annotations.length;i++){this.annotationViews_.push(annotations[i].getOrCreateView(this.viewport_));}
@@ -3430,54 +3492,64 @@
 return;var tracks=this.children;for(var i=0;i<tracks.length;++i)
 tracks[i].addEventsToTrackMap(eventToTrackMap);if(this.instantEvents===undefined)
 return;var vp=this.viewport_;this.instantEvents.forEach(function(ev){eventToTrackMap.addEvent(ev,this);}.bind(this));},addContainersToTrackMap:function(containerToTrackMap){var tracks=this.children;for(var i=0;i<tracks.length;++i)
-tracks[i].addContainersToTrackMap(containerToTrackMap);},appendKernelTrack_:function(){var kernel=this.model.kernel;var track=new tv.c.tracks.KernelTrack(this.viewport);track.kernel=this.model.kernel;if(!track.hasVisibleContent)
+tracks[i].addContainersToTrackMap(containerToTrackMap);},appendKernelTrack_:function(){var kernel=this.model.kernel;var track=new tr.c.tracks.KernelTrack(this.viewport);track.kernel=this.model.kernel;if(!track.hasVisibleContent)
 return;this.appendChild(track);},drawTrack:function(type){var ctx=this.context();if(!this.model_)
-return;var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));var dt=this.viewport.currentDisplayTransform;var viewLWorld=dt.xViewToWorld(0);var viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);switch(type){case tv.c.tracks.DrawType.GRID:this.viewport.drawMajorMarkLines(ctx);ctx.restore();return;case tv.c.tracks.DrawType.FLOW_ARROWS:if(this.model_.flowIntervalTree.size===0){ctx.restore();return;}
-this.drawFlowArrows_(viewLWorld,viewRWorld);ctx.restore();return;case tv.c.tracks.DrawType.INSTANT_EVENT:if(!this.model_.instantEvents||this.model_.instantEvents.length===0)
-break;tv.c.drawInstantSlicesAsLines(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.model_.instantEvents,4);break;case tv.c.tracks.DrawType.MARKERS:if(!this.viewport.interestRange.isEmpty){this.viewport.interestRange.draw(ctx,viewLWorld,viewRWorld);this.viewport.interestRange.drawIndicators(ctx,viewLWorld,viewRWorld);}
-ctx.restore();return;case tv.c.tracks.DrawType.HIGHLIGHTS:for(var i=0;i<this.highlighters_.length;i++){this.highlighters_[i].drawHighlight(ctx,dt,viewLWorld,viewRWorld,bounds.height);}
-ctx.restore();return;case tv.c.tracks.DrawType.ANNOTATIONS:for(var i=0;i<this.annotationViews_.length;i++){this.annotationViews_[i].draw(ctx);}
+return;var pixelRatio=window.devicePixelRatio||1;var bounds=this.getBoundingClientRect();var canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));var dt=this.viewport.currentDisplayTransform;var viewLWorld=dt.xViewToWorld(0);var viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);switch(type){case tr.c.tracks.DrawType.GRID:this.viewport.drawMajorMarkLines(ctx);ctx.restore();return;case tr.c.tracks.DrawType.FLOW_ARROWS:if(this.model_.flowIntervalTree.size===0){ctx.restore();return;}
+this.drawFlowArrows_(viewLWorld,viewRWorld);ctx.restore();return;case tr.c.tracks.DrawType.INSTANT_EVENT:if(!this.model_.instantEvents||this.model_.instantEvents.length===0)
+break;tr.c.drawInstantSlicesAsLines(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.model_.instantEvents,4);break;case tr.c.tracks.DrawType.MARKERS:if(!this.viewport.interestRange.isEmpty){this.viewport.interestRange.draw(ctx,viewLWorld,viewRWorld);this.viewport.interestRange.drawIndicators(ctx,viewLWorld,viewRWorld);}
+ctx.restore();return;case tr.c.tracks.DrawType.HIGHLIGHTS:for(var i=0;i<this.highlighters_.length;i++){this.highlighters_[i].drawHighlight(ctx,dt,viewLWorld,viewRWorld,bounds.height);}
+ctx.restore();return;case tr.c.tracks.DrawType.ANNOTATIONS:for(var i=0;i<this.annotationViews_.length;i++){this.annotationViews_[i].draw(ctx);}
 ctx.restore();return;}
-ctx.restore();tv.c.tracks.ContainerTrack.prototype.drawTrack.call(this,type);},drawFlowArrows_:function(viewLWorld,viewRWorld){var ctx=this.context();var dt=this.viewport.currentDisplayTransform;dt.applyTransformToCanvas(ctx);var pixWidth=dt.xViewVectorToWorld(1);ctx.strokeStyle='rgba(0, 0, 0, 0.4)';ctx.fillStyle='rgba(0, 0, 0, 0.4)';ctx.lineWidth=pixWidth>1.0?1:pixWidth;var events=this.model_.flowIntervalTree.findIntersection(viewLWorld,viewRWorld);var canvasBounds=ctx.canvas.getBoundingClientRect();for(var i=0;i<events.length;++i)
-this.drawFlowArrow_(ctx,events[i],canvasBounds,pixWidth);},drawFlowArrow_:function(ctx,flowEvent,canvasBounds,pixWidth){var pixelRatio=window.devicePixelRatio||1;var startTrack=this.viewport.trackForEvent(flowEvent.startSlice);var endTrack=this.viewport.trackForEvent(flowEvent.endSlice);if(startTrack===undefined||endTrack===undefined)
+ctx.restore();tr.c.tracks.ContainerTrack.prototype.drawTrack.call(this,type);},drawFlowArrows_:function(viewLWorld,viewRWorld){var ctx=this.context();var dt=this.viewport.currentDisplayTransform;dt.applyTransformToCanvas(ctx);var pixWidth=dt.xViewVectorToWorld(1);ctx.strokeStyle='rgba(0, 0, 0, 0.4)';ctx.fillStyle='rgba(0, 0, 0, 0.4)';ctx.lineWidth=pixWidth>1.0?1:pixWidth;var events=this.model_.flowIntervalTree.findIntersection(viewLWorld,viewRWorld);var onlyHighlighted=!this.viewport.showFlowEvents;var canvasBounds=ctx.canvas.getBoundingClientRect();for(var i=0;i<events.length;++i){if(onlyHighlighted&&events[i].selectionState!==SelectionState.SELECTED&&events[i].selectionState!==SelectionState.HIGHLIGHTED)
+continue;this.drawFlowArrow_(ctx,events[i],canvasBounds,pixWidth);}},drawFlowArrow_:function(ctx,flowEvent,canvasBounds,pixWidth){var pixelRatio=window.devicePixelRatio||1;var startTrack=this.viewport.trackForEvent(flowEvent.startSlice);var endTrack=this.viewport.trackForEvent(flowEvent.endSlice);if(startTrack===undefined||endTrack===undefined)
 return;var startBounds=startTrack.getBoundingClientRect();var endBounds=endTrack.getBoundingClientRect();if(flowEvent.selectionState==SelectionState.SELECTED){ctx.shadowBlur=1;ctx.shadowColor='red';ctx.shadowOffsety=2;ctx.strokeStyle='red';}else if(flowEvent.selectionState==SelectionState.HIGHLIGHTED){ctx.shadowBlur=1;ctx.shadowColor='red';ctx.shadowOffsety=2;ctx.strokeStyle='red';}else if(flowEvent.selectionState==SelectionState.DIMMED){ctx.shadowBlur=0;ctx.shadowOffsetX=0;ctx.strokeStyle='rgba(0, 0, 0, 0.2)';}else{var hasBoost=false;var startSlice=flowEvent.startSlice;hasBoost|=startSlice.selectionState===SelectionState.SELECTED;hasBoost|=startSlice.selectionState===SelectionState.HIGHLIGHTED;var endSlice=flowEvent.endSlice;hasBoost|=endSlice.selectionState===SelectionState.SELECTED;hasBoost|=endSlice.selectionState===SelectionState.HIGHLIGHTED;if(hasBoost){ctx.shadowBlur=1;ctx.shadowColor='rgba(255, 0, 0, 0.4)';ctx.shadowOffsety=2;ctx.strokeStyle='rgba(255, 0, 0, 0.4)';}else{ctx.shadowBlur=0;ctx.shadowOffsetX=0;ctx.strokeStyle='rgba(0, 0, 0, 0.4)';}}
 var startSize=startBounds.left+startBounds.top+
 startBounds.bottom+startBounds.right;var endSize=endBounds.left+endBounds.top+
 endBounds.bottom+endBounds.right;if(startSize===0&&endSize===0)
 return;var startY=this.calculateTrackY_(startTrack,canvasBounds);var endY=this.calculateTrackY_(endTrack,canvasBounds);var pixelStartY=pixelRatio*startY;var pixelEndY=pixelRatio*endY;var half=(flowEvent.end-flowEvent.start)/2;ctx.beginPath();ctx.moveTo(flowEvent.start,pixelStartY);ctx.bezierCurveTo(flowEvent.start+half,pixelStartY,flowEvent.start+half,pixelEndY,flowEvent.end,pixelEndY);ctx.stroke();var arrowWidth=5*pixWidth*pixelRatio;var distance=flowEvent.end-flowEvent.start;if(distance<=(2*arrowWidth))
-return;var tipX=flowEvent.end;var tipY=pixelEndY;var arrowHeight=(endBounds.height/4)*pixelRatio;tv.c.drawTriangle(ctx,tipX,tipY,tipX-arrowWidth,tipY-arrowHeight,tipX-arrowWidth,tipY+arrowHeight);ctx.fill();},calculateTrackY_:function(track,canvasBounds){var bounds=track.getBoundingClientRect();var size=bounds.left+bounds.top+bounds.bottom+bounds.right;if(size===0)
+return;var tipX=flowEvent.end;var tipY=pixelEndY;var arrowHeight=(endBounds.height/4)*pixelRatio;tr.c.drawTriangle(ctx,tipX,tipY,tipX-arrowWidth,tipY-arrowHeight,tipX-arrowWidth,tipY+arrowHeight);ctx.fill();},calculateTrackY_:function(track,canvasBounds){var bounds=track.getBoundingClientRect();var size=bounds.left+bounds.top+bounds.bottom+bounds.right;if(size===0)
 return this.calculateTrackY_(track.parentNode,canvasBounds);return bounds.top-canvasBounds.top+(bounds.height/2);},addIntersectingEventsInRangeToSelectionInWorldSpace:function(loWX,hiWX,viewPixWidthWorld,selection){function onPickHit(instantEvent){selection.push(instantEvent);}
-tv.b.iterateOverIntersectingIntervals(this.model_.instantEvents,function(x){return x.start;},function(x){return x.duration;},loWX,hiWX,onPickHit.bind(this));tv.c.tracks.ContainerTrack.prototype.addIntersectingEventsInRangeToSelectionInWorldSpace.apply(this,arguments);},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){this.addClosestInstantEventToSelection(this.model_.instantEvents,worldX,worldMaxDist,selection);tv.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.apply(this,arguments);}};return{TraceModelTrack:TraceModelTrack};});'use strict';tv.exportTo('tv.c.tracks',function(){var RulerTrack=tv.b.ui.define('ruler-track',tv.c.tracks.HeadingTrack);var logOf10=Math.log(10);function log10(x){return Math.log(x)/logOf10;}
-RulerTrack.prototype={__proto__:tv.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tv.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('ruler-track');this.strings_secs_=[];this.strings_msecs_=[];this.strings_usecs_=[];this.strings_nsecs_=[];this.viewportChange_=this.viewportChange_.bind(this);viewport.addEventListener('change',this.viewportChange_);},detach:function(){tv.c.tracks.HeadingTrack.prototype.detach.call(this);this.viewport.removeEventListener('change',this.viewportChange_);},viewportChange_:function(){if(this.viewport.interestRange.isEmpty)
+tr.b.iterateOverIntersectingIntervals(this.model_.instantEvents,function(x){return x.start;},function(x){return x.duration;},loWX,hiWX,onPickHit.bind(this));tr.c.tracks.ContainerTrack.prototype.addIntersectingEventsInRangeToSelectionInWorldSpace.apply(this,arguments);},addClosestEventToSelection:function(worldX,worldMaxDist,loY,hiY,selection){this.addClosestInstantEventToSelection(this.model_.instantEvents,worldX,worldMaxDist,selection);tr.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.apply(this,arguments);}};return{ModelTrack:ModelTrack};});'use strict';tr.exportTo('tr.c.tracks',function(){var RulerTrack=tr.b.ui.define('ruler-track',tr.c.tracks.HeadingTrack);var logOf10=Math.log(10);function log10(x){return Math.log(x)/logOf10;}
+RulerTrack.prototype={__proto__:tr.c.tracks.HeadingTrack.prototype,decorate:function(viewport){tr.c.tracks.HeadingTrack.prototype.decorate.call(this,viewport);this.classList.add('ruler-track');this.strings_secs_=[];this.strings_msecs_=[];this.strings_usecs_=[];this.strings_nsecs_=[];this.viewportChange_=this.viewportChange_.bind(this);viewport.addEventListener('change',this.viewportChange_);},detach:function(){tr.c.tracks.HeadingTrack.prototype.detach.call(this);this.viewport.removeEventListener('change',this.viewportChange_);},viewportChange_:function(){if(this.viewport.interestRange.isEmpty)
 this.classList.remove('tall-mode');else
-this.classList.add('tall-mode');},draw:function(type,viewLWorld,viewRWorld){switch(type){case tv.c.tracks.DrawType.GRID:this.drawGrid_(viewLWorld,viewRWorld);break;case tv.c.tracks.DrawType.MARKERS:if(!this.viewport.interestRange.isEmpty)
+this.classList.add('tall-mode');},draw:function(type,viewLWorld,viewRWorld){switch(type){case tr.c.tracks.DrawType.GRID:this.drawGrid_(viewLWorld,viewRWorld);break;case tr.c.tracks.DrawType.MARKERS:if(!this.viewport.interestRange.isEmpty)
 this.viewport.interestRange.draw(this.context(),viewLWorld,viewRWorld);break;}},drawGrid_:function(viewLWorld,viewRWorld){var ctx=this.context();var pixelRatio=window.devicePixelRatio||1;var canvasBounds=ctx.canvas.getBoundingClientRect();var trackBounds=this.getBoundingClientRect();var width=canvasBounds.width*pixelRatio;var height=trackBounds.height*pixelRatio;var hasInterestRange=!this.viewport.interestRange.isEmpty;var rulerHeight=hasInterestRange?(height*2)/5:height;var vp=this.viewport;var dt=vp.currentDisplayTransform;var idealMajorMarkDistancePix=150*pixelRatio;var idealMajorMarkDistanceWorld=dt.xViewVectorToWorld(idealMajorMarkDistancePix);var majorMarkDistanceWorld;var conservativeGuess=Math.pow(10,Math.ceil(log10(idealMajorMarkDistanceWorld)));var divisors=[10,5,2,1];for(var i=0;i<divisors.length;++i){var tightenedGuess=conservativeGuess/divisors[i];if(dt.xWorldVectorToView(tightenedGuess)<idealMajorMarkDistancePix)
 continue;majorMarkDistanceWorld=conservativeGuess/divisors[i-1];break;}
 var unit;var unitDivisor;var tickLabels=undefined;if(majorMarkDistanceWorld<0.0001){unit='ns';unitDivisor=0.000001;tickLabels=this.strings_nsecs_;}else if(majorMarkDistanceWorld<0.1){unit='us';unitDivisor=0.001;tickLabels=this.strings_usecs_;}else if(majorMarkDistanceWorld<100){unit='ms';unitDivisor=1;tickLabels=this.strings_msecs_;}else{unit='s';unitDivisor=1000;tickLabels=this.strings_secs_;}
 var numTicksPerMajor=5;var minorMarkDistanceWorld=majorMarkDistanceWorld/numTicksPerMajor;var minorMarkDistancePx=dt.xWorldVectorToView(minorMarkDistanceWorld);var firstMajorMark=Math.floor(viewLWorld/majorMarkDistanceWorld)*majorMarkDistanceWorld;var minorTickH=Math.floor(rulerHeight*0.25);ctx.save();var pixelRatio=window.devicePixelRatio||1;ctx.lineWidth=Math.round(pixelRatio);var crispLineCorrection=(ctx.lineWidth%2)/2;ctx.translate(crispLineCorrection,-crispLineCorrection);ctx.fillStyle='rgb(0, 0, 0)';ctx.strokeStyle='rgb(0, 0, 0)';ctx.textAlign='left';ctx.textBaseline='top';ctx.font=(9*pixelRatio)+'px sans-serif';vp.majorMarkPositions=[];ctx.beginPath();for(var curX=firstMajorMark;curX<viewRWorld;curX+=majorMarkDistanceWorld){var curXView=Math.floor(dt.xWorldToView(curX));var unitValue=curX/unitDivisor;var roundedUnitValue=Math.round(unitValue*100000)/100000;if(!tickLabels[roundedUnitValue])
-tickLabels[roundedUnitValue]=roundedUnitValue+' '+unit;ctx.fillText(tickLabels[roundedUnitValue],curXView+(2*pixelRatio),0);vp.majorMarkPositions.push(curXView);tv.c.drawLine(ctx,curXView,0,curXView,rulerHeight);for(var i=1;i<numTicksPerMajor;++i){var xView=Math.floor(curXView+minorMarkDistancePx*i);tv.c.drawLine(ctx,xView,rulerHeight-minorTickH,xView,rulerHeight);}}
-ctx.strokeStyle='rgb(0, 0, 0)';tv.c.drawLine(ctx,0,height,width,height);ctx.stroke();if(!hasInterestRange)
-return;tv.c.drawLine(ctx,0,rulerHeight,width,rulerHeight);ctx.stroke();var displayDistance;var displayTextColor='rgb(0,0,0)';var arrowSpacing=10*pixelRatio;var arrowColor='rgb(128,121,121)';var arrowPosY=rulerHeight*1.75;var arrowWidthView=3*pixelRatio;var arrowLengthView=10*pixelRatio;var spaceForArrowsView=2*(arrowWidthView+arrowSpacing);ctx.textBaseline='middle';ctx.font=(14*pixelRatio)+'px sans-serif';var textPosY=arrowPosY;var interestRange=vp.interestRange;if(interestRange.range===0){var markerWorld=interestRange.min;var markerView=dt.xWorldToView(markerWorld);var displayValue=markerWorld/unitDivisor;displayValue=Math.abs((Math.round(displayValue*1000)/1000));var textToDraw=displayValue+' '+unit;var textLeftView=markerView+4*pixelRatio;var textWidthView=ctx.measureText(textToDraw).width;if(textLeftView+textWidthView>width)
+tickLabels[roundedUnitValue]=roundedUnitValue+' '+unit;ctx.fillText(tickLabels[roundedUnitValue],curXView+(2*pixelRatio),0);vp.majorMarkPositions.push(curXView);tr.c.drawLine(ctx,curXView,0,curXView,rulerHeight);for(var i=1;i<numTicksPerMajor;++i){var xView=Math.floor(curXView+minorMarkDistancePx*i);tr.c.drawLine(ctx,xView,rulerHeight-minorTickH,xView,rulerHeight);}}
+ctx.strokeStyle='rgb(0, 0, 0)';tr.c.drawLine(ctx,0,height,width,height);ctx.stroke();if(!hasInterestRange)
+return;tr.c.drawLine(ctx,0,rulerHeight,width,rulerHeight);ctx.stroke();var displayDistance;var displayTextColor='rgb(0,0,0)';var arrowSpacing=10*pixelRatio;var arrowColor='rgb(128,121,121)';var arrowPosY=rulerHeight*1.75;var arrowWidthView=3*pixelRatio;var arrowLengthView=10*pixelRatio;var spaceForArrowsView=2*(arrowWidthView+arrowSpacing);ctx.textBaseline='middle';ctx.font=(14*pixelRatio)+'px sans-serif';var textPosY=arrowPosY;var interestRange=vp.interestRange;if(interestRange.range===0){var markerWorld=interestRange.min;var markerView=dt.xWorldToView(markerWorld);var displayValue=markerWorld/unitDivisor;displayValue=Math.abs((Math.round(displayValue*1000)/1000));var textToDraw=displayValue+' '+unit;var textLeftView=markerView+4*pixelRatio;var textWidthView=ctx.measureText(textToDraw).width;if(textLeftView+textWidthView>width)
 textLeftView=markerView-4*pixelRatio-textWidthView;ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);return;}
 var leftMarker=interestRange.min;var rightMarker=interestRange.max;var leftMarkerView=dt.xWorldToView(leftMarker);var rightMarkerView=dt.xWorldToView(rightMarker);var distanceBetweenMarkers=interestRange.range;var distanceBetweenMarkersView=dt.xWorldVectorToView(distanceBetweenMarkers);var positionInMiddleOfMarkersView=leftMarkerView+(distanceBetweenMarkersView/2);if(distanceBetweenMarkers<0.0001){unit='ns';unitDivisor=0.000001;}else if(distanceBetweenMarkers<0.1){unit='us';unitDivisor=0.001;}else if(distanceBetweenMarkers<100){unit='ms';unitDivisor=1;}else{unit='s';unitDivisor=1000;}
 displayDistance=distanceBetweenMarkers/unitDivisor;var roundedDisplayDistance=Math.abs((Math.round(displayDistance*1000)/1000));var textToDraw=roundedDisplayDistance+' '+unit;var textWidthView=ctx.measureText(textToDraw).width;var spaceForArrowsAndTextView=textWidthView+spaceForArrowsView+arrowSpacing;var textLeftView=positionInMiddleOfMarkersView-textWidthView/2;var textRightView=textLeftView+textWidthView;if(spaceForArrowsAndTextView>distanceBetweenMarkersView){textLeftView=rightMarkerView+2*arrowSpacing;if(textLeftView+textWidthView>width)
-textLeftView=leftMarkerView-2*arrowSpacing-textWidthView;ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);ctx.strokeStyle=arrowColor;ctx.beginPath();tv.c.drawLine(ctx,leftMarkerView,arrowPosY,rightMarkerView,arrowPosY);ctx.stroke();ctx.fillStyle=arrowColor;tv.c.drawArrow(ctx,leftMarkerView-1.5*arrowSpacing,arrowPosY,leftMarkerView,arrowPosY,arrowLengthView,arrowWidthView);tv.c.drawArrow(ctx,rightMarkerView+1.5*arrowSpacing,arrowPosY,rightMarkerView,arrowPosY,arrowLengthView,arrowWidthView);}else if(spaceForArrowsView<=distanceBetweenMarkersView){var leftArrowStart;var rightArrowStart;if(spaceForArrowsAndTextView<=distanceBetweenMarkersView){ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);leftArrowStart=textLeftView-arrowSpacing;rightArrowStart=textRightView+arrowSpacing;}else{leftArrowStart=positionInMiddleOfMarkersView;rightArrowStart=positionInMiddleOfMarkersView;}
-ctx.strokeStyle=arrowColor;ctx.fillStyle=arrowColor;tv.c.drawArrow(ctx,leftArrowStart,arrowPosY,leftMarkerView,arrowPosY,arrowLengthView,arrowWidthView);tv.c.drawArrow(ctx,rightArrowStart,arrowPosY,rightMarkerView,arrowPosY,arrowLengthView,arrowWidthView);}
-ctx.restore();},addIntersectingEventsInRangeToSelection:function(loVX,hiVX,loY,hiY,selection){},addAllEventsMatchingFilterToSelection:function(filter,selection){}};return{RulerTrack:RulerTrack};});'use strict';tv.exportTo('tv.c',function(){var Selection=tv.c.Selection;var SelectionState=tv.c.trace_model.SelectionState;var Viewport=tv.c.TimelineViewport;var tempDisplayTransform=new tv.c.TimelineDisplayTransform();function intersectRect_(r1,r2){var results=new Object;if(r2.left>r1.right||r2.right<r1.left||r2.top>r1.bottom||r2.bottom<r1.top){return false;}
+textLeftView=leftMarkerView-2*arrowSpacing-textWidthView;ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);ctx.strokeStyle=arrowColor;ctx.beginPath();tr.c.drawLine(ctx,leftMarkerView,arrowPosY,rightMarkerView,arrowPosY);ctx.stroke();ctx.fillStyle=arrowColor;tr.c.drawArrow(ctx,leftMarkerView-1.5*arrowSpacing,arrowPosY,leftMarkerView,arrowPosY,arrowLengthView,arrowWidthView);tr.c.drawArrow(ctx,rightMarkerView+1.5*arrowSpacing,arrowPosY,rightMarkerView,arrowPosY,arrowLengthView,arrowWidthView);}else if(spaceForArrowsView<=distanceBetweenMarkersView){var leftArrowStart;var rightArrowStart;if(spaceForArrowsAndTextView<=distanceBetweenMarkersView){ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);leftArrowStart=textLeftView-arrowSpacing;rightArrowStart=textRightView+arrowSpacing;}else{leftArrowStart=positionInMiddleOfMarkersView;rightArrowStart=positionInMiddleOfMarkersView;}
+ctx.strokeStyle=arrowColor;ctx.fillStyle=arrowColor;tr.c.drawArrow(ctx,leftArrowStart,arrowPosY,leftMarkerView,arrowPosY,arrowLengthView,arrowWidthView);tr.c.drawArrow(ctx,rightArrowStart,arrowPosY,rightMarkerView,arrowPosY,arrowLengthView,arrowWidthView);}
+ctx.restore();},addIntersectingEventsInRangeToSelection:function(loVX,hiVX,loY,hiY,selection){},addAllEventsMatchingFilterToSelection:function(filter,selection){}};return{RulerTrack:RulerTrack};});'use strict';tr.exportTo('tr.model',function(){function Annotation(){this.guid_=tr.b.GUID.allocate();this.view_=undefined;};Annotation.fromDictIfPossible=function(args){if(args.typeName===undefined)
+throw new Error('Missing typeName argument');var typeInfo=Annotation.findTypeInfoMatching(function(typeInfo){return typeInfo.metadata.typeName===args.typeName;});if(typeInfo===undefined)
+return undefined;return typeInfo.constructor.fromDict(args);};Annotation.fromDict=function(){throw new Error('Not implemented');}
+Annotation.prototype={get guid(){return this.guid_;},onRemove:function(){},toDict:function(){throw new Error('Not implemented');},getOrCreateView:function(viewport){if(!this.view_)
+this.view_=this.createView_(viewport);return this.view_;},createView_:function(){throw new Error('Not implemented');}};var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.mandatoryBaseType=Annotation;tr.b.decorateExtensionRegistry(Annotation,options);Annotation.addEventListener('will-register',function(e){if(!e.typeInfo.constructor.hasOwnProperty('fromDict'))
+throw new Error('Must have fromDict method');if(!e.typeInfo.metadata.typeName)
+throw new Error('Registered Annotations must provide typeName');});return{Annotation:Annotation};});'use strict';tr.exportTo('tr.c.annotations',function(){function AnnotationView(viewport,annotation){}
+AnnotationView.prototype={draw:function(ctx){throw new Error('Not implemented');}};return{AnnotationView:AnnotationView};});'use strict';tr.exportTo('tr.c.annotations',function(){function XMarkerAnnotationView(viewport,annotation){this.viewport_=viewport;this.annotation_=annotation;}
+XMarkerAnnotationView.prototype={__proto__:tr.c.annotations.AnnotationView.prototype,draw:function(ctx){var dt=this.viewport_.currentDisplayTransform;var viewX=dt.xWorldToView(this.annotation_.timestamp);ctx.beginPath();tr.c.drawLine(ctx,viewX,0,viewX,ctx.canvas.height);ctx.strokeStyle=this.annotation_.strokeStyle;ctx.stroke();}};return{XMarkerAnnotationView:XMarkerAnnotationView};});'use strict';tr.exportTo('tr.model',function(){function XMarkerAnnotation(timestamp){tr.model.Annotation.apply(this,arguments);this.timestamp=timestamp;this.strokeStyle='rgba(0, 0, 255, 0.5)';}
+XMarkerAnnotation.fromDict=function(dict){return new XMarkerAnnotation(dict.args.timestamp);}
+XMarkerAnnotation.prototype={__proto__:tr.model.Annotation.prototype,toDict:function(){return{typeName:'xmarker',args:{timestamp:this.timestamp}};},createView_:function(viewport){return new tr.c.annotations.XMarkerAnnotationView(viewport,this);}};tr.model.Annotation.register(XMarkerAnnotation,{typeName:'xmarker'});return{XMarkerAnnotation:XMarkerAnnotation};});'use strict';tr.exportTo('tr.c',function(){var Selection=tr.c.Selection;var SelectionState=tr.model.SelectionState;var Viewport=tr.c.TimelineViewport;var tempDisplayTransform=new tr.c.TimelineDisplayTransform();function intersectRect_(r1,r2){var results=new Object;if(r2.left>r1.right||r2.right<r1.left||r2.top>r1.bottom||r2.bottom<r1.top){return false;}
 results.left=Math.max(r1.left,r2.left);results.top=Math.max(r1.top,r2.top);results.right=Math.min(r1.right,r2.right);results.bottom=Math.min(r1.bottom,r2.bottom);results.width=(results.right-results.left);results.height=(results.bottom-results.top);return results;}
-var TimelineTrackView=tv.b.ui.define('div');TimelineTrackView.prototype={__proto__:HTMLDivElement.prototype,model_:null,decorate:function(timelineView){this.classList.add('timeline-track-view');this.timelineView_=timelineView;this.viewport_=new Viewport(this);this.viewportDisplayTransformAtMouseDown_=null;this.selectionController_=undefined;this.rulerTrackContainer_=new tv.c.tracks.DrawingContainer(this.viewport_);this.appendChild(this.rulerTrackContainer_);this.rulerTrackContainer_.invalidate();this.rulerTrack_=new tv.c.tracks.RulerTrack(this.viewport_);this.rulerTrackContainer_.appendChild(this.rulerTrack_);this.upperModelTrack_=new tv.c.tracks.TraceModelTrack(this.viewport_);this.upperModelTrack_.upperMode=true;this.rulerTrackContainer_.appendChild(this.upperModelTrack_);this.modelTrackContainer_=new tv.c.tracks.DrawingContainer(this.viewport_);this.appendChild(this.modelTrackContainer_);this.modelTrackContainer_.style.display='block';this.modelTrackContainer_.invalidate();this.viewport_.modelTrackContainer=this.modelTrackContainer_;this.modelTrack_=new tv.c.tracks.TraceModelTrack(this.viewport_);this.modelTrackContainer_.appendChild(this.modelTrack_);this.timingTool_=new tv.c.TimingTool(this.viewport_,this);this.initMouseModeSelector();this.dragBox_=this.ownerDocument.createElement('div');this.dragBox_.className='drag-box';this.appendChild(this.dragBox_);this.hideDragBox_();this.initHintText_();this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.bindEventListener_(document,'keypress',this.onKeypress_,this);this.bindEventListener_(document,'keydown',this.onKeydown_,this);this.bindEventListener_(document,'keyup',this.onKeyup_,this);this.bindEventListener_(this,'dblclick',this.onDblClick_,this);this.bindEventListener_(this,'mousewheel',this.onMouseWheel_,this);this.bindEventListener_(this,'mousedown',this.onMouseDown_,this);this.addEventListener('mousemove',this.onMouseMove_);this.addEventListener('touchstart',this.onTouchStart_);this.addEventListener('touchmove',this.onTouchMove_);this.addEventListener('touchend',this.onTouchEnd_);this.mouseViewPosAtMouseDown_={x:0,y:0};this.lastMouseViewPos_={x:0,y:0};this.lastTouchViewPositions_=[];this.alert_=undefined;this.isPanningAndScanning_=false;this.isZooming_=false;},bindEventListener_:function(object,event,func,target){if(!this.boundListeners_)
-this.boundListeners_=[];var boundFunc=func.bind(target);this.boundListeners_.push({object:object,event:event,boundFunc:boundFunc});object.addEventListener(event,boundFunc);},initMouseModeSelector:function(){this.mouseModeSelector_=new tv.b.ui.MouseModeSelector(this);this.appendChild(this.mouseModeSelector_);this.mouseModeSelector_.addEventListener('beginpan',this.onBeginPanScan_.bind(this));this.mouseModeSelector_.addEventListener('updatepan',this.onUpdatePanScan_.bind(this));this.mouseModeSelector_.addEventListener('endpan',this.onEndPanScan_.bind(this));this.mouseModeSelector_.addEventListener('beginselection',this.onBeginSelection_.bind(this));this.mouseModeSelector_.addEventListener('updateselection',this.onUpdateSelection_.bind(this));this.mouseModeSelector_.addEventListener('endselection',this.onEndSelection_.bind(this));this.mouseModeSelector_.addEventListener('beginzoom',this.onBeginZoom_.bind(this));this.mouseModeSelector_.addEventListener('updatezoom',this.onUpdateZoom_.bind(this));this.mouseModeSelector_.addEventListener('endzoom',this.onEndZoom_.bind(this));this.mouseModeSelector_.addEventListener('entertiming',this.timingTool_.onEnterTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('begintiming',this.timingTool_.onBeginTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('updatetiming',this.timingTool_.onUpdateTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('endtiming',this.timingTool_.onEndTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('exittiming',this.timingTool_.onExitTiming.bind(this.timingTool_));var m=tv.b.ui.MOUSE_SELECTOR_MODE;this.mouseModeSelector_.supportedModeMask=m.SELECTION|m.PANSCAN|m.ZOOM|m.TIMING;this.mouseModeSelector_.settingsKey='timelineTrackView.mouseModeSelector';this.mouseModeSelector_.setKeyCodeForMode(m.PANSCAN,'2'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.SELECTION,'1'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.ZOOM,'3'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.TIMING,'4'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeCondition(function(){return this.listenToKeys_;}.bind(this));this.mouseModeSelector_.setModifierForAlternateMode(m.SELECTION,tv.b.ui.MODIFIER.SHIFT);this.mouseModeSelector_.setModifierForAlternateMode(m.PANSCAN,tv.b.ui.MODIFIER.SPACE);this.mouseModeSelector_.setModifierForAlternateMode(m.ZOOM,tv.b.ui.MODIFIER.CMD_OR_CTRL);},get selectionController(){return this.selectionController_;},set selectionController(selectionController){if(this.selectionController_){this.selectionController_.removeEventListener('change',this.onSelectionChanged_);}
+var TimelineTrackView=tr.b.ui.define('div');TimelineTrackView.prototype={__proto__:HTMLDivElement.prototype,model_:null,decorate:function(timelineView){this.classList.add('timeline-track-view');this.timelineView_=timelineView;this.viewport_=new Viewport(this);this.viewportDisplayTransformAtMouseDown_=null;this.selectionController_=undefined;this.rulerTrackContainer_=new tr.c.tracks.DrawingContainer(this.viewport_);this.appendChild(this.rulerTrackContainer_);this.rulerTrackContainer_.invalidate();this.rulerTrack_=new tr.c.tracks.RulerTrack(this.viewport_);this.rulerTrackContainer_.appendChild(this.rulerTrack_);this.upperModelTrack_=new tr.c.tracks.ModelTrack(this.viewport_);this.upperModelTrack_.upperMode=true;this.rulerTrackContainer_.appendChild(this.upperModelTrack_);this.modelTrackContainer_=new tr.c.tracks.DrawingContainer(this.viewport_);this.appendChild(this.modelTrackContainer_);this.modelTrackContainer_.style.display='block';this.modelTrackContainer_.invalidate();this.viewport_.modelTrackContainer=this.modelTrackContainer_;this.modelTrack_=new tr.c.tracks.ModelTrack(this.viewport_);this.modelTrackContainer_.appendChild(this.modelTrack_);this.timingTool_=new tr.c.TimingTool(this.viewport_,this);this.initMouseModeSelector();this.dragBox_=this.ownerDocument.createElement('div');this.dragBox_.className='drag-box';this.appendChild(this.dragBox_);this.hideDragBox_();this.initHintText_();this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.bindEventListener_(document,'keypress',this.onKeypress_,this);this.bindEventListener_(document,'keydown',this.onKeydown_,this);this.bindEventListener_(document,'keyup',this.onKeyup_,this);this.bindEventListener_(this,'dblclick',this.onDblClick_,this);this.bindEventListener_(this,'mousewheel',this.onMouseWheel_,this);this.bindEventListener_(this,'mousedown',this.onMouseDown_,this);this.addEventListener('mousemove',this.onMouseMove_);this.addEventListener('touchstart',this.onTouchStart_);this.addEventListener('touchmove',this.onTouchMove_);this.addEventListener('touchend',this.onTouchEnd_);this.mouseViewPosAtMouseDown_={x:0,y:0};this.lastMouseViewPos_={x:0,y:0};this.lastTouchViewPositions_=[];this.alert_=undefined;this.isPanningAndScanning_=false;this.isZooming_=false;},bindEventListener_:function(object,event,func,target){if(!this.boundListeners_)
+this.boundListeners_=[];var boundFunc=func.bind(target);this.boundListeners_.push({object:object,event:event,boundFunc:boundFunc});object.addEventListener(event,boundFunc);},initMouseModeSelector:function(){this.mouseModeSelector_=new tr.b.ui.MouseModeSelector(this);this.appendChild(this.mouseModeSelector_);this.mouseModeSelector_.addEventListener('beginpan',this.onBeginPanScan_.bind(this));this.mouseModeSelector_.addEventListener('updatepan',this.onUpdatePanScan_.bind(this));this.mouseModeSelector_.addEventListener('endpan',this.onEndPanScan_.bind(this));this.mouseModeSelector_.addEventListener('beginselection',this.onBeginSelection_.bind(this));this.mouseModeSelector_.addEventListener('updateselection',this.onUpdateSelection_.bind(this));this.mouseModeSelector_.addEventListener('endselection',this.onEndSelection_.bind(this));this.mouseModeSelector_.addEventListener('beginzoom',this.onBeginZoom_.bind(this));this.mouseModeSelector_.addEventListener('updatezoom',this.onUpdateZoom_.bind(this));this.mouseModeSelector_.addEventListener('endzoom',this.onEndZoom_.bind(this));this.mouseModeSelector_.addEventListener('entertiming',this.timingTool_.onEnterTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('begintiming',this.timingTool_.onBeginTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('updatetiming',this.timingTool_.onUpdateTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('endtiming',this.timingTool_.onEndTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('exittiming',this.timingTool_.onExitTiming.bind(this.timingTool_));var m=tr.b.ui.MOUSE_SELECTOR_MODE;this.mouseModeSelector_.supportedModeMask=m.SELECTION|m.PANSCAN|m.ZOOM|m.TIMING;this.mouseModeSelector_.settingsKey='timelineTrackView.mouseModeSelector';this.mouseModeSelector_.setKeyCodeForMode(m.PANSCAN,'2'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.SELECTION,'1'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.ZOOM,'3'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.TIMING,'4'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeCondition(function(){return this.listenToKeys_;}.bind(this));this.mouseModeSelector_.setModifierForAlternateMode(m.SELECTION,tr.b.ui.MODIFIER.SHIFT);this.mouseModeSelector_.setModifierForAlternateMode(m.PANSCAN,tr.b.ui.MODIFIER.SPACE);this.mouseModeSelector_.setModifierForAlternateMode(m.ZOOM,tr.b.ui.MODIFIER.CMD_OR_CTRL);},get selectionController(){return this.selectionController_;},set selectionController(selectionController){if(this.selectionController_){this.selectionController_.removeEventListener('change',this.onSelectionChanged_);}
 this.selectionController_=selectionController;if(this.selectionController_){this.selectionController_.addEventListener('change',this.onSelectionChanged_);}},onSelectionChanged_:function(){this.showHintText_('Press \'m\' to mark current selection');this.viewport_.dispatchChangeEvent();},set selection(selection){throw new Error('DO NOT CALL THIS');},set highlight(highlight){throw new Error('DO NOT CALL THIS');},detach:function(){this.modelTrack_.detach();this.upperModelTrack_.detach();for(var i=0;i<this.boundListeners_.length;i++){var binding=this.boundListeners_[i];binding.object.removeEventListener(binding.event,binding.boundFunc);}
 this.boundListeners_=undefined;this.viewport_.detach();},get viewport(){return this.viewport_;},get model(){return this.model_;},set model(model){if(!model)
 throw new Error('Model cannot be null');var modelInstanceChanged=this.model_!==model;this.model_=model;this.modelTrack_.model=model;this.upperModelTrack_.model=model;if(modelInstanceChanged)
-this.viewport_.setWhenPossible(this.setInitialViewport_.bind(this));tv.b.setPropertyAndDispatchChange(this,'model',model);},get hasVisibleContent(){return this.modelTrack_.hasVisibleContent||this.upperModelTrack_.hasVisibleContent;},setInitialViewport_:function(){this.modelTrackContainer_.updateCanvasSizeIfNeeded_();var w=this.modelTrackContainer_.canvas.width;var min;var range;if(this.model_.bounds.isEmpty){min=0;range=1000;}else if(this.model_.bounds.range===0){min=this.model_.bounds.min;range=1000;}else{min=this.model_.bounds.min;range=this.model_.bounds.range;}
+this.viewport_.setWhenPossible(this.setInitialViewport_.bind(this));tr.b.setPropertyAndDispatchChange(this,'model',model);},get hasVisibleContent(){return this.modelTrack_.hasVisibleContent||this.upperModelTrack_.hasVisibleContent;},setInitialViewport_:function(){this.modelTrackContainer_.updateCanvasSizeIfNeeded_();var w=this.modelTrackContainer_.canvas.width;var min;var range;if(this.model_.bounds.isEmpty){min=0;range=1000;}else if(this.model_.bounds.range===0){min=this.model_.bounds.min;range=1000;}else{min=this.model_.bounds.min;range=this.model_.bounds.range;}
 var boost=range*0.15;tempDisplayTransform.set(this.viewport_.currentDisplayTransform);tempDisplayTransform.xSetWorldBounds(min-boost,min+range+boost,w);this.viewport_.setDisplayTransformImmediately(tempDisplayTransform);},addAllEventsMatchingFilterToSelectionAsTask:function(filter,selection){var modelTrack=this.modelTrack_;var firstT=modelTrack.addAllEventsMatchingFilterToSelectionAsTask(filter,selection);var lastT=firstT.after(function(){this.upperModelTrack_.addAllEventsMatchingFilterToSelection(filter,selection);},this);return firstT;},get focusElement(){if(this.focusElement_)
 return this.focusElement_;return this.parentElement;},set focusElement(value){this.focusElement_=value;},get listenToKeys_(){if(!this.viewport_.isAttachedToDocumentOrInTestMode)
 return false;if(document.activeElement instanceof TracingFindControl)
 return false;if(document.activeElement instanceof TracingScriptingControl)
 return false;if(!this.focusElement_)
 return true;if(this.focusElement.tabIndex>=0){if(document.activeElement==this.focusElement)
-return true;return tv.b.ui.elementIsChildOf(document.activeElement,this.focusElement);}
+return true;return tr.b.ui.elementIsChildOf(document.activeElement,this.focusElement);}
 return true;},onMouseMove_:function(e){if(this.isZooming_)
 return;this.storeLastMousePos_(e);},onTouchStart_:function(e){this.storeLastTouchPositions_(e);this.focusElements_();},onTouchMove_:function(e){e.preventDefault();this.onUpdateTransformForTouch_(e);},onTouchEnd_:function(e){this.storeLastTouchPositions_(e);this.focusElements_();},onKeypress_:function(e){var vp=this.viewport_;if(!this.listenToKeys_)
 return;if(document.activeElement.nodeName=='INPUT')
@@ -3488,27 +3560,27 @@
 this.selectPrevious_(e);else
 this.selectNext_(e);e.preventDefault();}
 break;}},onKeyup_:function(e){if(!this.listenToKeys_)
-return;if(!e.shiftKey){if(this.dragBeginEvent_){this.setDragBoxPosition_(this.dragBoxXStart_,this.dragBoxYStart_,this.dragBoxXEnd_,this.dragBoxYEnd_);}}},onDblClick_:function(e){if(this.mouseModeSelector_.mode!==tv.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
+return;if(!e.shiftKey){if(this.dragBeginEvent_){this.setDragBoxPosition_(this.dragBoxXStart_,this.dragBoxYStart_,this.dragBoxXEnd_,this.dragBoxYEnd_);}}},onDblClick_:function(e){if(this.mouseModeSelector_.mode!==tr.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
 return;var curSelection=this.selectionController_.selection;if(!curSelection.length||!curSelection[0].title)
-return;var selection=new Selection();var filter=new tv.c.ExactTitleFilter(curSelection[0].title);this.modelTrack_.addAllEventsMatchingFilterToSelection(filter,selection);this.selectionController.changeSelectionFromTimeline(selection);},onMouseWheel_:function(e){if(!e.altKey)
-return;var delta=e.wheelDelta/120;var zoomScale=Math.pow(1.5,delta);this.zoomBy_(zoomScale);e.preventDefault();},onMouseDown_:function(e){if(this.mouseModeSelector_.mode!==tv.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
+return;var selection=new Selection();var filter=new tr.c.ExactTitleFilter(curSelection[0].title);this.modelTrack_.addAllEventsMatchingFilterToSelection(filter,selection);this.selectionController.changeSelectionFromTimeline(selection);},onMouseWheel_:function(e){if(!e.altKey)
+return;var delta=e.wheelDelta/120;var zoomScale=Math.pow(1.5,delta);this.zoomBy_(zoomScale);e.preventDefault();},onMouseDown_:function(e){if(this.mouseModeSelector_.mode!==tr.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
 return;if(e.target!==this.rulerTrack_)
 return;this.dragBeginEvent_=undefined;if(this.xNavStringMarker_){this.model.removeAnnotation(this.xNavStringMarker_);this.xNavStringMarker_=undefined;}
-var dt=this.viewport_.currentDisplayTransform;tv.b.ui.trackMouseMovesUntilMouseUp(function(e){if(e.target===this.rulerTrack_)
-return;var relativePosition=this.extractRelativeMousePosition_(e);var loc=tv.c.Location.fromViewCoordinates(this.viewport_,relativePosition.x,relativePosition.y);if(!loc)
-return;if(this.guideLineAnnotation_===undefined){this.guideLineAnnotation_=new tv.c.trace_model.XMarkerAnnotation(loc.xWorld);this.model.addAnnotation(this.guideLineAnnotation_);}else{this.guideLineAnnotation_.timestamp=loc.xWorld;this.modelTrackContainer_.invalidate();}
-var state=new tv.c.UIState(loc,this.viewport_.currentDisplayTransform.scaleX);this.timelineView_.setFindCtlText(state.toUserFriendlyString(this.viewport_));}.bind(this));},queueSmoothPan_:function(viewDeltaX,deltaY){var deltaX=this.viewport_.currentDisplayTransform.xViewVectorToWorld(viewDeltaX);var animation=new tv.c.TimelineDisplayTransformPanAnimation(deltaX,deltaY);this.viewport_.queueDisplayTransformAnimation(animation);},zoomBy_:function(scale,smooth){if(scale<=0){return;}
-smooth=!!smooth;var vp=this.viewport_;var viewWidth=this.modelTrackContainer_.canvas.clientWidth;var pixelRatio=window.devicePixelRatio||1;var goalFocalPointXView=this.lastMouseViewPos_.x*pixelRatio;var goalFocalPointXWorld=vp.currentDisplayTransform.xViewToWorld(goalFocalPointXView);if(smooth){var animation=new tv.c.TimelineDisplayTransformZoomToAnimation(goalFocalPointXWorld,goalFocalPointXView,vp.currentDisplayTransform.panY,scale);vp.queueDisplayTransformAnimation(animation);}else{tempDisplayTransform.set(vp.currentDisplayTransform);tempDisplayTransform.scaleX=tempDisplayTransform.scaleX*scale;tempDisplayTransform.xPanWorldPosToViewPos(goalFocalPointXWorld,goalFocalPointXView,viewWidth);vp.setDisplayTransformImmediately(tempDisplayTransform);}},zoomToSelection:function(){if(!this.selectionController.selectionOfInterest.length)
+var dt=this.viewport_.currentDisplayTransform;tr.b.ui.trackMouseMovesUntilMouseUp(function(e){if(e.target===this.rulerTrack_)
+return;var relativePosition=this.extractRelativeMousePosition_(e);var loc=tr.c.Location.fromViewCoordinates(this.viewport_,relativePosition.x,relativePosition.y);if(!loc)
+return;if(this.guideLineAnnotation_===undefined){this.guideLineAnnotation_=new tr.model.XMarkerAnnotation(loc.xWorld);this.model.addAnnotation(this.guideLineAnnotation_);}else{this.guideLineAnnotation_.timestamp=loc.xWorld;this.modelTrackContainer_.invalidate();}
+var state=new tr.c.UIState(loc,this.viewport_.currentDisplayTransform.scaleX);this.timelineView_.setFindCtlText(state.toUserFriendlyString(this.viewport_));}.bind(this));},queueSmoothPan_:function(viewDeltaX,deltaY){var deltaX=this.viewport_.currentDisplayTransform.xViewVectorToWorld(viewDeltaX);var animation=new tr.c.TimelineDisplayTransformPanAnimation(deltaX,deltaY);this.viewport_.queueDisplayTransformAnimation(animation);},zoomBy_:function(scale,smooth){if(scale<=0){return;}
+smooth=!!smooth;var vp=this.viewport_;var viewWidth=this.modelTrackContainer_.canvas.clientWidth;var pixelRatio=window.devicePixelRatio||1;var goalFocalPointXView=this.lastMouseViewPos_.x*pixelRatio;var goalFocalPointXWorld=vp.currentDisplayTransform.xViewToWorld(goalFocalPointXView);if(smooth){var animation=new tr.c.TimelineDisplayTransformZoomToAnimation(goalFocalPointXWorld,goalFocalPointXView,vp.currentDisplayTransform.panY,scale);vp.queueDisplayTransformAnimation(animation);}else{tempDisplayTransform.set(vp.currentDisplayTransform);tempDisplayTransform.scaleX=tempDisplayTransform.scaleX*scale;tempDisplayTransform.xPanWorldPosToViewPos(goalFocalPointXWorld,goalFocalPointXView,viewWidth);vp.setDisplayTransformImmediately(tempDisplayTransform);}},zoomToSelection:function(){if(!this.selectionController.selectionOfInterest.length)
 return;var bounds=this.selectionController.selectionOfInterest.bounds;if(!bounds.range)
-return;var worldCenter=bounds.center;var viewCenter=this.modelTrackContainer_.canvas.width/2;var adjustedWorldRange=bounds.range*1.25;var newScale=this.modelTrackContainer_.canvas.width/adjustedWorldRange;var zoomInRatio=newScale/this.viewport_.currentDisplayTransform.scaleX;var animation=new tv.c.TimelineDisplayTransformZoomToAnimation(worldCenter,viewCenter,this.viewport_.currentDisplayTransform.panY,zoomInRatio);this.viewport_.queueDisplayTransformAnimation(animation);},panToSelection:function(){if(!this.selectionController.selectionOfInterest.length)
-return;var bounds=this.selectionController.selectionOfInterest.bounds;var worldCenter=bounds.center;var viewWidth=this.modelTrackContainer_.canvas.width;var dt=this.viewport_.currentDisplayTransform;if(false&&!bounds.range){if(dt.xWorldToView(bounds.center)<0||dt.xWorldToView(bounds.center)>viewWidth){tempDisplayTransform.set(dt);tempDisplayTransform.xPanWorldPosToViewPos(worldCenter,'center',viewWidth);var deltaX=tempDisplayTransform.panX-dt.panX;var animation=new tv.c.TimelineDisplayTransformPanAnimation(deltaX,0);this.viewport_.queueDisplayTransformAnimation(animation);}
+return;var worldCenter=bounds.center;var viewCenter=this.modelTrackContainer_.canvas.width/2;var adjustedWorldRange=bounds.range*1.25;var newScale=this.modelTrackContainer_.canvas.width/adjustedWorldRange;var zoomInRatio=newScale/this.viewport_.currentDisplayTransform.scaleX;var animation=new tr.c.TimelineDisplayTransformZoomToAnimation(worldCenter,viewCenter,this.viewport_.currentDisplayTransform.panY,zoomInRatio);this.viewport_.queueDisplayTransformAnimation(animation);},panToSelection:function(){if(!this.selectionController.selectionOfInterest.length)
+return;var bounds=this.selectionController.selectionOfInterest.bounds;var worldCenter=bounds.center;var viewWidth=this.modelTrackContainer_.canvas.width;var dt=this.viewport_.currentDisplayTransform;if(false&&!bounds.range){if(dt.xWorldToView(bounds.center)<0||dt.xWorldToView(bounds.center)>viewWidth){tempDisplayTransform.set(dt);tempDisplayTransform.xPanWorldPosToViewPos(worldCenter,'center',viewWidth);var deltaX=tempDisplayTransform.panX-dt.panX;var animation=new tr.c.TimelineDisplayTransformPanAnimation(deltaX,0);this.viewport_.queueDisplayTransformAnimation(animation);}
 return;}
-tempDisplayTransform.set(dt);tempDisplayTransform.xPanWorldBoundsIntoView(bounds.min,bounds.max,viewWidth);var deltaX=tempDisplayTransform.panX-dt.panX;var animation=new tv.c.TimelineDisplayTransformPanAnimation(deltaX,0);this.viewport_.queueDisplayTransformAnimation(animation);},navToPosition:function(uiState,showNavLine){var location=uiState.location;var scaleX=uiState.scaleX;var track=location.getContainingTrack(this.viewport_);var worldCenter=location.xWorld;var viewCenter=this.modelTrackContainer_.canvas.width/5;var zoomInRatio=scaleX/this.viewport_.currentDisplayTransform.scaleX;track.scrollIntoViewIfNeeded();var animation=new tv.c.TimelineDisplayTransformZoomToAnimation(worldCenter,viewCenter,this.viewport_.currentDisplayTransform.panY,zoomInRatio);this.viewport_.queueDisplayTransformAnimation(animation);if(!showNavLine)
+tempDisplayTransform.set(dt);tempDisplayTransform.xPanWorldBoundsIntoView(bounds.min,bounds.max,viewWidth);var deltaX=tempDisplayTransform.panX-dt.panX;var animation=new tr.c.TimelineDisplayTransformPanAnimation(deltaX,0);this.viewport_.queueDisplayTransformAnimation(animation);},navToPosition:function(uiState,showNavLine){var location=uiState.location;var scaleX=uiState.scaleX;var track=location.getContainingTrack(this.viewport_);var worldCenter=location.xWorld;var viewCenter=this.modelTrackContainer_.canvas.width/5;var zoomInRatio=scaleX/this.viewport_.currentDisplayTransform.scaleX;track.scrollIntoViewIfNeeded();var animation=new tr.c.TimelineDisplayTransformZoomToAnimation(worldCenter,viewCenter,this.viewport_.currentDisplayTransform.panY,zoomInRatio);this.viewport_.queueDisplayTransformAnimation(animation);if(!showNavLine)
 return;if(this.xNavStringMarker_)
-this.model.removeAnnotation(this.xNavStringMarker_);this.xNavStringMarker_=new tv.c.trace_model.XMarkerAnnotation(worldCenter);this.model.addAnnotation(this.xNavStringMarker_);},setCurrentSelectionAsInterestRange_:function(){var selectionBounds=this.selectionController_.selection.bounds;if(selectionBounds.empty){this.viewport_.interestRange.reset();return;}
+this.model.removeAnnotation(this.xNavStringMarker_);this.xNavStringMarker_=new tr.model.XMarkerAnnotation(worldCenter);this.model.addAnnotation(this.xNavStringMarker_);},setCurrentSelectionAsInterestRange_:function(){var selectionBounds=this.selectionController_.selection.bounds;if(selectionBounds.empty){this.viewport_.interestRange.reset();return;}
 if(this.viewport_.interestRange.min==selectionBounds.min&&this.viewport_.interestRange.max==selectionBounds.max)
 this.viewport_.interestRange.reset();else
-this.viewport_.interestRange.set(selectionBounds);},toggleHighDetails_:function(){this.viewport_.highDetails=!this.viewport_.highDetails;},hideDragBox_:function(){this.dragBox_.style.left='-1000px';this.dragBox_.style.top='-1000px';this.dragBox_.style.width=0;this.dragBox_.style.height=0;},setDragBoxPosition_:function(xStart,yStart,xEnd,yEnd){var loY=Math.min(yStart,yEnd);var hiY=Math.max(yStart,yEnd);var loX=Math.min(xStart,xEnd);var hiX=Math.max(xStart,xEnd);var modelTrackRect=this.modelTrack_.getBoundingClientRect();var dragRect={left:loX,top:loY,width:hiX-loX,height:hiY-loY};dragRect.right=dragRect.left+dragRect.width;dragRect.bottom=dragRect.top+dragRect.height;var modelTrackContainerRect=this.modelTrackContainer_.getBoundingClientRect();var clipRect={left:modelTrackContainerRect.left,top:modelTrackContainerRect.top,right:modelTrackContainerRect.right,bottom:modelTrackContainerRect.bottom};var headingWidth=window.getComputedStyle(this.querySelector('heading')).width;var trackTitleWidth=parseInt(headingWidth);clipRect.left=clipRect.left+trackTitleWidth;var finalDragBox=intersectRect_(clipRect,dragRect);this.dragBox_.style.left=finalDragBox.left+'px';this.dragBox_.style.width=finalDragBox.width+'px';this.dragBox_.style.top=finalDragBox.top+'px';this.dragBox_.style.height=finalDragBox.height+'px';this.dragBox_.style.whiteSpace='nowrap';var pixelRatio=window.devicePixelRatio||1;var canv=this.modelTrackContainer_.canvas;var dt=this.viewport_.currentDisplayTransform;var loWX=dt.xViewToWorld((loX-canv.offsetLeft)*pixelRatio);var hiWX=dt.xViewToWorld((hiX-canv.offsetLeft)*pixelRatio);this.dragBox_.textContent=tv.c.analysis.tsString((hiWX-loWX));var e=new tv.b.Event('selectionChanging');e.loWX=loWX;e.hiWX=hiWX;this.dispatchEvent(e);},onGridToggle_:function(left){var selection=this.selectionController_.selection;var tb=left?selection.bounds.min:selection.bounds.max;if(this.viewport_.gridEnabled&&this.viewport_.gridSide===left&&this.viewport_.gridInitialTimebase===tb){this.viewport_.gridside=undefined;this.viewport_.gridEnabled=false;this.viewport_.gridInitialTimebase=undefined;return;}
+this.viewport_.interestRange.set(selectionBounds);},toggleHighDetails_:function(){this.viewport_.highDetails=!this.viewport_.highDetails;},hideDragBox_:function(){this.dragBox_.style.left='-1000px';this.dragBox_.style.top='-1000px';this.dragBox_.style.width=0;this.dragBox_.style.height=0;},setDragBoxPosition_:function(xStart,yStart,xEnd,yEnd){var loY=Math.min(yStart,yEnd);var hiY=Math.max(yStart,yEnd);var loX=Math.min(xStart,xEnd);var hiX=Math.max(xStart,xEnd);var modelTrackRect=this.modelTrack_.getBoundingClientRect();var dragRect={left:loX,top:loY,width:hiX-loX,height:hiY-loY};dragRect.right=dragRect.left+dragRect.width;dragRect.bottom=dragRect.top+dragRect.height;var modelTrackContainerRect=this.modelTrackContainer_.getBoundingClientRect();var clipRect={left:modelTrackContainerRect.left,top:modelTrackContainerRect.top,right:modelTrackContainerRect.right,bottom:modelTrackContainerRect.bottom};var headingWidth=window.getComputedStyle(this.querySelector('heading')).width;var trackTitleWidth=parseInt(headingWidth);clipRect.left=clipRect.left+trackTitleWidth;var finalDragBox=intersectRect_(clipRect,dragRect);this.dragBox_.style.left=finalDragBox.left+'px';this.dragBox_.style.width=finalDragBox.width+'px';this.dragBox_.style.top=finalDragBox.top+'px';this.dragBox_.style.height=finalDragBox.height+'px';this.dragBox_.style.whiteSpace='nowrap';var pixelRatio=window.devicePixelRatio||1;var canv=this.modelTrackContainer_.canvas;var dt=this.viewport_.currentDisplayTransform;var loWX=dt.xViewToWorld((loX-canv.offsetLeft)*pixelRatio);var hiWX=dt.xViewToWorld((hiX-canv.offsetLeft)*pixelRatio);this.dragBox_.textContent=tr.b.units.tsString((hiWX-loWX));var e=new tr.b.Event('selectionChanging');e.loWX=loWX;e.hiWX=hiWX;this.dispatchEvent(e);},onGridToggle_:function(left){var selection=this.selectionController_.selection;var tb=left?selection.bounds.min:selection.bounds.max;if(this.viewport_.gridEnabled&&this.viewport_.gridSide===left&&this.viewport_.gridInitialTimebase===tb){this.viewport_.gridside=undefined;this.viewport_.gridEnabled=false;this.viewport_.gridInitialTimebase=undefined;return;}
 var numIntervalsSinceStart=Math.ceil((tb-this.model_.bounds.min)/this.viewport_.gridStep_);this.viewport_.gridEnabled=true;this.viewport_.gridSide=left;this.viewport_.gridInitialTimebase=tb;this.viewport_.gridTimebase=tb-
 (numIntervalsSinceStart+1)*this.viewport_.gridStep_;},storeLastMousePos_:function(e){this.lastMouseViewPos_=this.extractRelativeMousePosition_(e);},storeLastTouchPositions_:function(e){this.lastTouchViewPositions_=this.extractRelativeTouchPositions_(e);},extractRelativeMousePosition_:function(e){var canv=this.modelTrackContainer_.canvas;return{x:e.clientX-canv.offsetLeft,y:e.clientY-canv.offsetTop};},extractRelativeTouchPositions_:function(e){var canv=this.modelTrackContainer_.canvas;var touches=[];for(var i=0;i<e.touches.length;++i){touches.push({x:e.touches[i].clientX-canv.offsetLeft,y:e.touches[i].clientY-canv.offsetTop});}
 return touches;},storeInitialMouseDownPos_:function(e){var position=this.extractRelativeMousePosition_(e);this.mouseViewPosAtMouseDown_.x=position.x;this.mouseViewPosAtMouseDown_.y=position.y;},focusElements_:function(){if(document.activeElement)
@@ -3529,10 +3601,10 @@
 (yMin-yMax)*(yMin-yMax));},onUpdateTransformForTouch_:function(e){var newPositions=this.extractRelativeTouchPositions_(e);var currentPositions=this.lastTouchViewPositions_;var newCenter=this.computeTouchCenter_(newPositions);var currentCenter=this.computeTouchCenter_(currentPositions);var newSpan=this.computeTouchSpan_(newPositions);var currentSpan=this.computeTouchSpan_(currentPositions);var vp=this.viewport_;var viewWidth=this.modelTrackContainer_.canvas.clientWidth;var pixelRatio=window.devicePixelRatio||1;var xDelta=pixelRatio*(newCenter.x-currentCenter.x);var yDelta=newCenter.y-currentCenter.y;var zoomScaleValue=currentSpan>10?newSpan/currentSpan:1;var viewFocus=pixelRatio*newCenter.x;var worldFocus=vp.currentDisplayTransform.xViewToWorld(viewFocus);tempDisplayTransform.set(vp.currentDisplayTransform);tempDisplayTransform.scaleX*=zoomScaleValue;tempDisplayTransform.xPanWorldPosToViewPos(worldFocus,viewFocus,viewWidth);tempDisplayTransform.incrementPanXInViewUnits(xDelta);tempDisplayTransform.panY-=yDelta;vp.setDisplayTransformImmediately(tempDisplayTransform);this.storeLastTouchPositions_(e);},initHintText_:function(){this.hintTextBox_=this.ownerDocument.createElement('div');this.hintTextBox_.className='hint-text';this.hintTextBox_.style.display='none';this.appendChild(this.hintTextBox_);this.pendingHintTextClearTimeout_=undefined;},showHintText_:function(text){if(this.pendingHintTextClearTimeout_){window.clearTimeout(this.pendingHintTextClearTimeout_);this.pendingHintTextClearTimeout_=undefined;}
 this.pendingHintTextClearTimeout_=setTimeout(this.hideHintText_.bind(this),1000);this.hintTextBox_.textContent=text;this.hintTextBox_.style.display='';},hideHintText_:function(){this.pendingHintTextClearTimeout_=undefined;this.hintTextBox_.style.display='none';}};return{TimelineTrackView:TimelineTrackView};});'use strict';Polymer('tracing-find-control',{filterKeyDown:function(e){if(e.keyCode===27)
 return;e.stopPropagation();if(e.keyCode!==13)return;e.shiftKey?this.findPrevious():this.findNext();},filterKeyPress:function(e){if(e.keyCode===27)
-return;e.stopPropagation();},filterBlur:function(e){this.updateHitCountEl();},filterFocus:function(e){this.controller.reset();this.$.filter.select();},filterMouseUp:function(e){e.preventDefault();},get controller(){return this.controller_;},set controller(c){this.controller_=c;this.updateHitCountEl();},focus:function(){this.$.filter.focus();},get hasFocus(){return this===document.activeElement;},filterTextChanged:function(){this.controller.filterText=this.$.filter.value;this.$.hitCount.textContent='';this.$.spinner.style.visibility='visible';this.controller.updateFilterHits().then(function(){this.$.spinner.style.visibility='hidden';this.updateHitCountEl();}.bind(this));},findNext:function(){if(this.controller)
+return;e.stopPropagation();},filterBlur:function(e){this.updateHitCountEl();},filterFocus:function(e){this.$.filter.select();},filterMouseUp:function(e){e.preventDefault();},get controller(){return this.controller_;},set controller(c){this.controller_=c;this.updateHitCountEl();},focus:function(){this.$.filter.focus();},get hasFocus(){return this===document.activeElement;},filterTextChanged:function(){this.$.hitCount.textContent='';this.$.spinner.style.visibility='visible';this.controller.startFiltering(this.$.filter.value).then(function(){this.$.spinner.style.visibility='hidden';this.updateHitCountEl();}.bind(this));},findNext:function(){if(this.controller)
 this.controller.findNext();this.updateHitCountEl();},findPrevious:function(){if(this.controller)
 this.controller.findPrevious();this.updateHitCountEl();},updateHitCountEl:function(){if(!this.controller||!this.hasFocus){this.$.hitCount.textContent='';return;}
-var n=this.controller.filterHits.length;var i=n===0?-1:this.controller.currentHitIndex;this.$.hitCount.textContent=(i+1)+' of '+n;},setText:function(string){this.$.filter.value=string;}});'use strict';tv.exportTo('tv.c',function(){var Selection=tv.c.Selection;var SelectionState=tv.c.trace_model.SelectionState;function BrushingState(){this.guid_=tv.b.GUID.allocate();this.selection_=new Selection();this.findMatches_=new Selection();this.analysisViewRelatedEvents_=new Selection();this.appliedToModel_=undefined;}
+var n=this.controller.filterHits.length;var i=n===0?-1:this.controller.currentHitIndex;this.$.hitCount.textContent=(i+1)+' of '+n;},setText:function(string){this.$.filter.value=string;}});'use strict';tr.exportTo('tr.c',function(){var Selection=tr.c.Selection;var SelectionState=tr.model.SelectionState;function BrushingState(){this.guid_=tr.b.GUID.allocate();this.selection_=new Selection();this.findMatches_=new Selection();this.analysisViewRelatedEvents_=new Selection();this.appliedToModel_=undefined;}
 BrushingState.prototype={get guid(){return this.guid_;},clone:function(){var that=new BrushingState();that.selection_=this.selection_;that.findMatches_=this.findMatches_;that.analysisViewRelatedEvents_=this.analysisViewRelatedEvents_;return that;},equals:function(that){if(!this.selection_.equals(that.selection_))
 return false;if(!this.findMatches_.equals(that.findMatches_))
 return false;if(!this.analysisViewRelatedEvents_.equals(that.analysisViewRelatedEvents_)){return false;}
@@ -3550,78 +3622,78 @@
 e.selectionState=selectionState;}.bind(this));},transferModelOwnershipToClone:function(that){if(!this.appliedToModel_)
 throw new Error('Not applied');that.appliedToModel_=this.appliedToModel_;this.appliedToModel_=undefined;},unapplyFromModelSelectionState:function(){if(!this.appliedToModel_)
 throw new Error('Not applied');var model=this.appliedToModel_;this.appliedToModel_=undefined;if(!this.hasHighlight_){this.selection_.forEach(function(e){e.selectionState=SelectionState.NONE;});return;}
-model.iterateAllEvents(function(e){e.selectionState=SelectionState.NONE;});}};return{BrushingState:BrushingState};});'use strict';tv.exportTo('tv.c',function(){function YComponent(stableId,yPercentOffset){this.stableId=stableId;this.yPercentOffset=yPercentOffset;}
-YComponent.prototype={toDict:function(){return{stableId:this.stableId,yPercentOffset:this.yPercentOffset};}};function Location(xWorld,yComponents){this.xWorld_=xWorld;this.yComponents_=yComponents;};Location.fromViewCoordinates=function(viewport,viewX,viewY){var dt=viewport.currentDisplayTransform;var xWorld=dt.xViewToWorld(viewX);var yComponents=[];var elem=document.elementFromPoint(viewX+viewport.modelTrackContainer.canvas.offsetLeft,viewY+viewport.modelTrackContainer.canvas.offsetTop);while(elem instanceof tv.c.tracks.Track){if(elem.eventContainer){var boundRect=elem.getBoundingClientRect();var yPercentOffset=(viewY-boundRect.top)/boundRect.height;yComponents.push(new YComponent(elem.eventContainer.stableId,yPercentOffset));}
+model.iterateAllEvents(function(e){e.selectionState=SelectionState.NONE;});}};return{BrushingState:BrushingState};});'use strict';tr.exportTo('tr.c',function(){function YComponent(stableId,yPercentOffset){this.stableId=stableId;this.yPercentOffset=yPercentOffset;}
+YComponent.prototype={toDict:function(){return{stableId:this.stableId,yPercentOffset:this.yPercentOffset};}};function Location(xWorld,yComponents){this.xWorld_=xWorld;this.yComponents_=yComponents;};Location.fromViewCoordinates=function(viewport,viewX,viewY){var dt=viewport.currentDisplayTransform;var xWorld=dt.xViewToWorld(viewX);var yComponents=[];var elem=document.elementFromPoint(viewX+viewport.modelTrackContainer.canvas.offsetLeft,viewY+viewport.modelTrackContainer.canvas.offsetTop);while(elem instanceof tr.c.tracks.Track){if(elem.eventContainer){var boundRect=elem.getBoundingClientRect();var yPercentOffset=(viewY-boundRect.top)/boundRect.height;yComponents.push(new YComponent(elem.eventContainer.stableId,yPercentOffset));}
 elem=elem.parentElement;}
 if(yComponents.length==0)
 return;return new Location(xWorld,yComponents);}
 Location.fromStableIdAndTimestamp=function(viewport,stableId,ts){var xWorld=ts;var yComponents=[];var containerToTrack=viewport.containerToTrackObj;var elem=containerToTrack.getTrackByStableId(stableId);if(!elem)
-return;var firstY=elem.getBoundingClientRect().top;while(elem instanceof tv.c.tracks.Track){if(elem.eventContainer){var boundRect=elem.getBoundingClientRect();var yPercentOffset=(firstY-boundRect.top)/boundRect.height;yComponents.push(new YComponent(elem.eventContainer.stableId,yPercentOffset));}
+return;var firstY=elem.getBoundingClientRect().top;while(elem instanceof tr.c.tracks.Track){if(elem.eventContainer){var boundRect=elem.getBoundingClientRect();var yPercentOffset=(firstY-boundRect.top)/boundRect.height;yComponents.push(new YComponent(elem.eventContainer.stableId,yPercentOffset));}
 elem=elem.parentElement;}
 if(yComponents.length==0)
 return;return new Location(xWorld,yComponents);}
 Location.prototype={get xWorld(){return this.xWorld_;},getContainingTrack:function(viewport){var containerToTrack=viewport.containerToTrackObj;for(var i in this.yComponents_){var yComponent=this.yComponents_[i];var track=containerToTrack.getTrackByStableId(yComponent.stableId);if(track!==undefined)
 return track;}},toViewCoordinates:function(viewport){var dt=viewport.currentDisplayTransform;var containerToTrack=viewport.containerToTrackObj;var viewX=dt.xWorldToView(this.xWorld_);var viewY=-1;for(var index in this.yComponents_){var yComponent=this.yComponents_[index];var track=containerToTrack.getTrackByStableId(yComponent.stableId);if(track!==undefined){var boundRect=track.getBoundingClientRect();viewY=yComponent.yPercentOffset*boundRect.height+boundRect.top;break;}}
-return{viewX:viewX,viewY:viewY};},toDict:function(){return{xWorld:this.xWorld_,yComponents:this.yComponents_};}};return{Location:Location};});'use strict';tv.exportTo('tv.c',function(){var Location=tv.c.Location;function UIState(location,scaleX){this.location_=location;this.scaleX_=scaleX;};UIState.fromUserFriendlyString=function(model,viewport,stateString){var navByFinderPattern=/^(-?\d+(\.\d+)?)@(.+)x(\d+(\.\d+)?)$/g;var match=navByFinderPattern.exec(stateString);if(!match)
+return{viewX:viewX,viewY:viewY};},toDict:function(){return{xWorld:this.xWorld_,yComponents:this.yComponents_};}};return{Location:Location};});'use strict';tr.exportTo('tr.c',function(){var Location=tr.c.Location;function UIState(location,scaleX){this.location_=location;this.scaleX_=scaleX;};UIState.fromUserFriendlyString=function(model,viewport,stateString){var navByFinderPattern=/^(-?\d+(\.\d+)?)@(.+)x(\d+(\.\d+)?)$/g;var match=navByFinderPattern.exec(stateString);if(!match)
 return;var timestamp=parseFloat(match[1]);var stableId=match[3];var scaleX=parseFloat(match[4]);if(scaleX<=0)
 throw new Error('Invalid ScaleX value in UI State string.');if(!viewport.containerToTrackObj.getTrackByStableId(stableId))
-throw new Error('Invalid StableID given in UI State String.');var loc=tv.c.Location.fromStableIdAndTimestamp(viewport,stableId,timestamp);return new UIState(loc,scaleX);}
-UIState.prototype={get location(){return this.location_;},get scaleX(){return this.scaleX_;},toUserFriendlyString:function(viewport){var timestamp=this.location_.xWorld;var stableId=this.location_.getContainingTrack(viewport).eventContainer.stableId;var scaleX=this.scaleX_;return timestamp.toFixed(5)+'@'+stableId+'x'+scaleX.toFixed(5);},toDict:function(){return{location:this.location_.toDict(),scaleX:this.scaleX_};}};return{UIState:UIState};});'use strict';tv.exportTo('tv.c',function(){var BrushingState=tv.c.BrushingState;var Selection=tv.c.Selection;var SelectionState=tv.c.trace_model.SelectionState;var Viewport=tv.c.TimelineViewport;function SelectionController(timelineView){tv.b.EventTarget.call(this);this.timelineView_=timelineView;this.currentBrushingState_=new BrushingState();this.onPopState_=this.onPopState_.bind(this);this.historyEnabled_=false;this.selections_={};}
-SelectionController.prototype={__proto__:tv.b.EventTarget.prototype,dispatchChangeEvent_:function(){var e=new tv.b.Event('change',false,false);this.dispatchEvent(e);},get model(){if(!this.timelineView_)
+throw new Error('Invalid StableID given in UI State String.');var loc=tr.c.Location.fromStableIdAndTimestamp(viewport,stableId,timestamp);return new UIState(loc,scaleX);}
+UIState.prototype={get location(){return this.location_;},get scaleX(){return this.scaleX_;},toUserFriendlyString:function(viewport){var timestamp=this.location_.xWorld;var stableId=this.location_.getContainingTrack(viewport).eventContainer.stableId;var scaleX=this.scaleX_;return timestamp.toFixed(5)+'@'+stableId+'x'+scaleX.toFixed(5);},toDict:function(){return{location:this.location_.toDict(),scaleX:this.scaleX_};}};return{UIState:UIState};});'use strict';tr.exportTo('tr.c',function(){var BrushingState=tr.c.BrushingState;var Selection=tr.c.Selection;var SelectionState=tr.model.SelectionState;var Viewport=tr.c.TimelineViewport;function SelectionController(timelineView){tr.b.EventTarget.call(this);this.timelineView_=timelineView;this.currentBrushingState_=new BrushingState();this.onPopState_=this.onPopState_.bind(this);this.historyEnabled_=false;this.selections_={};}
+SelectionController.prototype={__proto__:tr.b.EventTarget.prototype,dispatchChangeEvent_:function(){var e=new tr.b.Event('change',false,false);this.dispatchEvent(e);},get model(){if(!this.timelineView_)
 return undefined;return this.timelineView_.model;},get trackView(){if(!this.timelineView_)
 return undefined;return this.timelineView_.trackView;},get viewport(){if(!this.timelineView_)
 return undefined;if(!this.timelineView_.trackView)
 return undefined;return this.timelineView_.trackView.viewport;},get historyEnabled(){return this.historyEnabled_;},set historyEnabled(historyEnabled){this.historyEnabled_=!!historyEnabled;if(historyEnabled)
 window.addEventListener('popstate',this.onPopState_);else
 window.removeEventListener('popstate',this.onPopState_);},modelWillChange:function(){if(this.currentBrushingState_.isAppliedToModel)
-this.currentBrushingState_.unapplyFromModelSelectionState();},modelDidChange:function(){this.selections_={};this.currentBrushingState_.applyToModelSelectionState(this.model);var e=new tv.b.Event('model-changed',false,false);this.dispatchEvent(e);},onUserInitiatedSelectionChange_:function(){var selection=this.selection;if(this.historyEnabled){this.selections_[selection.guid]=selection;var state={selection_guid:selection.guid};window.history.pushState(state,document.title);}},onPopState_:function(e){if(e.state===null)
+this.currentBrushingState_.unapplyFromModelSelectionState();},modelDidChange:function(){this.selections_={};this.currentBrushingState_.applyToModelSelectionState(this.model);var e=new tr.b.Event('model-changed',false,false);this.dispatchEvent(e);},onUserInitiatedSelectionChange_:function(){var selection=this.selection;if(this.historyEnabled){this.selections_[selection.guid]=selection;var state={selection_guid:selection.guid};window.history.pushState(state,document.title);}},onPopState_:function(e){if(e.state===null)
 return;var selection=this.selections_[e.state.selection_guid];if(selection){var newState=this.currentBrushingState_.clone();newState.selection=selection;this.currentBrushingState=newState;}
 e.stopPropagation();},get selection(){return this.currentBrushingState_.selection;},get findMatches(){return this.currentBrushingState_.findMatches;},get selectionOfInterest(){return this.currentBrushingState_.selectionOfInterest;},get currentBrushingState(){return this.currentBrushingState_;},set currentBrushingState(newBrushingState){if(newBrushingState.isAppliedToModel)
 throw new Error('Cannot apply this state, it is applied');var hasValueChanged=!this.currentBrushingState_.equals(newBrushingState);if(newBrushingState!==this.currentBrushingState_&&hasValueChanged==false){this.currentBrushingState_.transferModelOwnershipToClone(newBrushingState);this.currentBrushingState_=newBrushingState;return;}
 if(this.currentBrushingState_.isAppliedToModel)
 this.currentBrushingState_.unapplyFromModelSelectionState();this.currentBrushingState_=newBrushingState;if(this.model)
 this.currentBrushingState_.applyToModelSelectionState(this.model);this.dispatchChangeEvent_();},addAllEventsMatchingFilterToSelectionAsTask:function(filter,selection){var timelineView=this.timelineView_.trackView;if(!timelineView)
-return new tv.b.Task();return timelineView.addAllEventsMatchingFilterToSelectionAsTask(filter,selection);},findTextChangedTo:function(allPossibleMatches){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.findMatches=allPossibleMatches;this.currentBrushingState=newBrushingState;},findFocusChangedTo:function(currentFocus){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=currentFocus;this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},findTextCleared:function(){if(this.xNavStringMarker_!==undefined){this.model.removeAnnotation(this.xNavStringMarker_);this.xNavStringMarker_=undefined;}
+return new tr.b.Task();return timelineView.addAllEventsMatchingFilterToSelectionAsTask(filter,selection);},findTextChangedTo:function(allPossibleMatches){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.findMatches=allPossibleMatches;this.currentBrushingState=newBrushingState;},findFocusChangedTo:function(currentFocus){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=currentFocus;this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},findTextCleared:function(){if(this.xNavStringMarker_!==undefined){this.model.removeAnnotation(this.xNavStringMarker_);this.xNavStringMarker_=undefined;}
 if(this.guideLineAnnotation_!==undefined){this.model.removeAnnotation(this.guideLineAnnotation_);this.guideLineAnnotation_=undefined;}
-var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=new Selection();newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},uiStateFromString:function(string){return tv.c.UIState.fromUserFriendlyString(this.model,this.viewport,string);},navToPosition:function(uiState,showNavLine){this.trackView.navToPosition(uiState,showNavLine);},changeSelectionFromTimeline:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},showScriptControlSelection:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;},changeSelectionFromRequestSelectionChangeEvent:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},changeAnalysisViewRelatedEvents:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.analysisViewRelatedEvents=selection;this.currentBrushingState=newBrushingState;}};return{SelectionController:SelectionController};});'use strict';tv.exportTo('tv.c',function(){function ScriptingObject(){}
-ScriptingObject.prototype={onModelChanged:function(){}};return{ScriptingObject:ScriptingObject};});'use strict';tv.exportTo('tv.c',function(){function ScriptingController(selectionController){this.selectionController_=selectionController;this.scriptObjectNames_=[];this.scriptObjectValues_=[];this.selectionController.addEventListener('model-changed',this.onModelChanged_.bind(this));var typeInfos=ScriptingObjectRegistry.getAllRegisteredTypeInfos();typeInfos.forEach(function(typeInfo){this.addScriptObject(typeInfo.metadata.name,typeInfo.constructor);window[typeInfo.metadata.name]=typeInfo.constructor;}.bind(this));}
+var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=new Selection();newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},uiStateFromString:function(string){return tr.c.UIState.fromUserFriendlyString(this.model,this.viewport,string);},navToPosition:function(uiState,showNavLine){this.trackView.navToPosition(uiState,showNavLine);},changeSelectionFromTimeline:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},showScriptControlSelection:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;},changeSelectionFromRequestSelectionChangeEvent:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new Selection();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},changeAnalysisViewRelatedEvents:function(selection){var newBrushingState=this.currentBrushingState_.clone();newBrushingState.analysisViewRelatedEvents=selection;this.currentBrushingState=newBrushingState;}};return{SelectionController:SelectionController};});'use strict';tr.exportTo('tr.c',function(){function ScriptingObject(){}
+ScriptingObject.prototype={onModelChanged:function(){}};return{ScriptingObject:ScriptingObject};});'use strict';tr.exportTo('tr.c',function(){function ScriptingController(selectionController){this.selectionController_=selectionController;this.scriptObjectNames_=[];this.scriptObjectValues_=[];this.selectionController.addEventListener('model-changed',this.onModelChanged_.bind(this));var typeInfos=ScriptingObjectRegistry.getAllRegisteredTypeInfos();typeInfos.forEach(function(typeInfo){this.addScriptObject(typeInfo.metadata.name,typeInfo.constructor);window[typeInfo.metadata.name]=typeInfo.constructor;}.bind(this));}
 function ScriptingObjectRegistry(){}
-var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);tv.b.decorateExtensionRegistry(ScriptingObjectRegistry,options);ScriptingController.prototype={get selectionController(){return this.selectionController_;},onModelChanged_:function(){this.scriptObjectValues_.forEach(function(v){if(v.onModelChanged)
-v.onModelChanged();});},addScriptObject:function(name,value){this.scriptObjectNames_.push(name);this.scriptObjectValues_.push(value);},executeCommand:function(command){var f=new Function(this.scriptObjectNames_,'return eval('+command+')');return f.apply(null,this.scriptObjectValues_);}};return{ScriptingController:ScriptingController,ScriptingObjectRegistry:ScriptingObjectRegistry};});'use strict';tv.exportTo('tv.e.tquery',function(){function Context(){this.event=undefined;this.ancestors=[];}
-Context.prototype={push:function(event){var ctx=new Context();ctx.ancestors=this.ancestors.slice();ctx.ancestors.push(event);return ctx;},pop:function(event){var ctx=new Context();ctx.event=this.ancestors[this.ancestors.length-1];ctx.ancestors=this.ancestors.slice(0,this.ancestors.length-1);return ctx;}};return{Context:Context};});'use strict';tv.exportTo('tv.e.tquery',function(){function Filter(){tv.c.ScriptingObject.call(this);}
-Filter.normalizeFilterExpression=function(filterExpression){if(filterExpression instanceof String||typeof(filterExpression)=='string'||filterExpression instanceof RegExp){var filter=new tv.e.tquery.FilterHasTitle(filterExpression);return filter;}
-return filterExpression;};Filter.prototype={__proto__:tv.c.ScriptingObject.prototype,evaluate:function(context){throw new Error('Not implemented');},matchValue_:function(value,expected){if(expected instanceof RegExp)
+var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);tr.b.decorateExtensionRegistry(ScriptingObjectRegistry,options);ScriptingController.prototype={get selectionController(){return this.selectionController_;},onModelChanged_:function(){this.scriptObjectValues_.forEach(function(v){if(v.onModelChanged)
+v.onModelChanged();});},addScriptObject:function(name,value){this.scriptObjectNames_.push(name);this.scriptObjectValues_.push(value);},executeCommand:function(command){var f=new Function(this.scriptObjectNames_,'return eval('+command+')');return f.apply(null,this.scriptObjectValues_);}};return{ScriptingController:ScriptingController,ScriptingObjectRegistry:ScriptingObjectRegistry};});'use strict';tr.exportTo('tr.e.tquery',function(){function Context(){this.event=undefined;this.ancestors=[];}
+Context.prototype={push:function(event){var ctx=new Context();ctx.ancestors=this.ancestors.slice();ctx.ancestors.push(event);return ctx;},pop:function(event){var ctx=new Context();ctx.event=this.ancestors[this.ancestors.length-1];ctx.ancestors=this.ancestors.slice(0,this.ancestors.length-1);return ctx;}};return{Context:Context};});'use strict';tr.exportTo('tr.e.tquery',function(){function Filter(){tr.c.ScriptingObject.call(this);}
+Filter.normalizeFilterExpression=function(filterExpression){if(filterExpression instanceof String||typeof(filterExpression)=='string'||filterExpression instanceof RegExp){var filter=new tr.e.tquery.FilterHasTitle(filterExpression);return filter;}
+return filterExpression;};Filter.prototype={__proto__:tr.c.ScriptingObject.prototype,evaluate:function(context){throw new Error('Not implemented');},matchValue_:function(value,expected){if(expected instanceof RegExp)
 return expected.test(value);else if(expected instanceof Function)
-return expected(value);return value===expected;}};return{Filter:Filter};});'use strict';tv.exportTo('tv.e.tquery',function(){function FilterAllOf(opt_subExpressions){tv.e.tquery.Filter.call(this);this.subExpressions=opt_subExpressions||[];}
-FilterAllOf.prototype={__proto__:tv.e.tquery.Filter.prototype,set subExpressions(exprs){this.subExpressions_=[];for(var i=0;i<exprs.length;i++){this.subExpressions_.push(tv.e.tquery.Filter.normalizeFilterExpression(exprs[i]));}},get subExpressions(){return this.subExpressions_;},evaluate:function(context){if(!this.subExpressions.length)
+return expected(value);return value===expected;}};return{Filter:Filter};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterAllOf(opt_subExpressions){tr.e.tquery.Filter.call(this);this.subExpressions=opt_subExpressions||[];}
+FilterAllOf.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpressions(exprs){this.subExpressions_=[];for(var i=0;i<exprs.length;i++){this.subExpressions_.push(tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));}},get subExpressions(){return this.subExpressions_;},evaluate:function(context){if(!this.subExpressions.length)
 return true;for(var i=0;i<this.subExpressions.length;i++){if(!this.subExpressions[i].evaluate(context))
 return false;}
-return true;}};tv.c.ScriptingObjectRegistry.register(function(){var exprs=[];for(var i=0;i<arguments.length;i++){exprs.push(arguments[i]);}
-return new FilterAllOf(exprs);},{name:'allOf'});return{FilterAllOf:FilterAllOf};});'use strict';tv.exportTo('tv.e.tquery',function(){function FilterAnyOf(opt_subExpressions){tv.e.tquery.Filter.call(this);this.subExpressions=opt_subExpressions||[];};FilterAnyOf.prototype={__proto__:tv.e.tquery.Filter.prototype,set subExpressions(exprs){this.subExpressions_=[];for(var i=0;i<exprs.length;i++){this.subExpressions_.push(tv.e.tquery.Filter.normalizeFilterExpression(exprs[i]));}},get subExpressions(){return this.subExpressions_;},evaluate:function(context){if(!this.subExpressions.length)
+return true;}};tr.c.ScriptingObjectRegistry.register(function(){var exprs=[];for(var i=0;i<arguments.length;i++){exprs.push(arguments[i]);}
+return new FilterAllOf(exprs);},{name:'allOf'});return{FilterAllOf:FilterAllOf};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterAnyOf(opt_subExpressions){tr.e.tquery.Filter.call(this);this.subExpressions=opt_subExpressions||[];};FilterAnyOf.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpressions(exprs){this.subExpressions_=[];for(var i=0;i<exprs.length;i++){this.subExpressions_.push(tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));}},get subExpressions(){return this.subExpressions_;},evaluate:function(context){if(!this.subExpressions.length)
 return true;for(var i=0;i<this.subExpressions.length;i++){if(this.subExpressions[i].evaluate(context))
 return true;}
-return false;}};tv.c.ScriptingObjectRegistry.register(function(){var exprs=[];for(var i=0;i<arguments.length;i++){exprs.push(arguments[i]);}
-return new FilterAnyOf(exprs);},{name:'anyOf'});return{FilterAnyOf:FilterAnyOf};});'use strict';tv.exportTo('tv.e.tquery',function(){function FilterHasAncestor(opt_subExpression){this.subExpression=opt_subExpression;};FilterHasAncestor.prototype={__proto__:tv.e.tquery.Filter.prototype,set subExpression(expr){this.subExpression_=tv.e.tquery.Filter.normalizeFilterExpression(expr);},get subExpression(){return this.subExpression_;},evaluate:function(context){if(!this.subExpression)
+return false;}};tr.c.ScriptingObjectRegistry.register(function(){var exprs=[];for(var i=0;i<arguments.length;i++){exprs.push(arguments[i]);}
+return new FilterAnyOf(exprs);},{name:'anyOf'});return{FilterAnyOf:FilterAnyOf};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterHasAncestor(opt_subExpression){this.subExpression=opt_subExpression;};FilterHasAncestor.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpression(expr){this.subExpression_=tr.e.tquery.Filter.normalizeFilterExpression(expr);},get subExpression(){return this.subExpression_;},evaluate:function(context){if(!this.subExpression)
 return context.ancestors.length>0;while(context.ancestors.length){context=context.pop();if(this.subExpression.evaluate(context))
 return true;}
-return false;}};tv.c.ScriptingObjectRegistry.register(function(subExpression){return new FilterHasAncestor(subExpression);},{name:'hasAncestor'});return{FilterHasAncestor:FilterHasAncestor};});'use strict';tv.exportTo('tv.e.tquery',function(){function FilterHasDuration(minValueOrExpected,opt_maxValue){if(minValueOrExpected!==undefined&&opt_maxValue!==undefined){this.minValue=minValueOrExpected;this.maxValue=opt_maxValue;}else{this.expected=minValueOrExpected;}};FilterHasDuration.prototype={__proto__:tv.e.tquery.Filter.prototype,evaluate:function(context){if(context.event.duration===undefined)
+return false;}};tr.c.ScriptingObjectRegistry.register(function(subExpression){return new FilterHasAncestor(subExpression);},{name:'hasAncestor'});return{FilterHasAncestor:FilterHasAncestor};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterHasDuration(minValueOrExpected,opt_maxValue){if(minValueOrExpected!==undefined&&opt_maxValue!==undefined){this.minValue=minValueOrExpected;this.maxValue=opt_maxValue;}else{this.expected=minValueOrExpected;}};FilterHasDuration.prototype={__proto__:tr.e.tquery.Filter.prototype,evaluate:function(context){if(context.event.duration===undefined)
 return false;if(this.minValue!==undefined&&this.maxValue!==undefined){return context.event.duration>=this.minValue&&context.event.duration<=this.maxValue;}
-return this.matchValue_(context.event.duration,this.expected);}};tv.c.ScriptingObjectRegistry.register(function(minValueOrExpected,opt_maxValue){return new FilterHasDuration(minValueOrExpected,opt_maxValue);},{name:'hasDuration'});return{FilterHasDuration:FilterHasDuration};});'use strict';tv.exportTo('tv.e.tquery',function(){function FilterHasTitle(expected){tv.e.tquery.Filter.call(this);this.expected=expected;}
-FilterHasTitle.prototype={__proto__:tv.e.tquery.Filter.prototype,evaluate:function(context){return this.matchValue_(context.event.title,this.expected);}};tv.c.ScriptingObjectRegistry.register(function(expected){var filter=new tv.e.tquery.FilterHasTitle(expected);return filter;},{name:'hasTitle'});return{FilterHasTitle:FilterHasTitle};});'use strict';tv.exportTo('tv.e.tquery',function(){function FilterIsTopLevel(opt_subExpression){this.subExpression=opt_subExpression;}
-FilterIsTopLevel.prototype={__proto__:tv.e.tquery.Filter.prototype,set subExpression(expr){this.subExpression_=tv.e.tquery.Filter.normalizeFilterExpression(expr);},get subExpression(){return this.subExpression_;},evaluate:function(context){if(context.ancestors.length>0)
+return this.matchValue_(context.event.duration,this.expected);}};tr.c.ScriptingObjectRegistry.register(function(minValueOrExpected,opt_maxValue){return new FilterHasDuration(minValueOrExpected,opt_maxValue);},{name:'hasDuration'});return{FilterHasDuration:FilterHasDuration};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterHasTitle(expected){tr.e.tquery.Filter.call(this);this.expected=expected;}
+FilterHasTitle.prototype={__proto__:tr.e.tquery.Filter.prototype,evaluate:function(context){return this.matchValue_(context.event.title,this.expected);}};tr.c.ScriptingObjectRegistry.register(function(expected){var filter=new tr.e.tquery.FilterHasTitle(expected);return filter;},{name:'hasTitle'});return{FilterHasTitle:FilterHasTitle};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterIsTopLevel(opt_subExpression){this.subExpression=opt_subExpression;}
+FilterIsTopLevel.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpression(expr){this.subExpression_=tr.e.tquery.Filter.normalizeFilterExpression(expr);},get subExpression(){return this.subExpression_;},evaluate:function(context){if(context.ancestors.length>0)
 return false;if(!this.subExpression)
-return true;return this.subExpression.evaluate(context);}};tv.c.ScriptingObjectRegistry.register(function(subExpression){return new FilterIsTopLevel(subExpression);},{name:'isTopLevel'});return{FilterIsTopLevel:FilterIsTopLevel};});'use strict';tv.exportTo('tv.e.tquery',function(){function TQuery(selectionController){tv.c.ScriptingObject.call(this);this.selectionController_=selectionController;this.parent_=undefined;this.filterExpression_=undefined;this.selection_=undefined;};TQuery.prototype={__proto__:tv.c.ScriptingObject.prototype,onModelChanged:function(){this.selection_=undefined;},get selectionController(){return this.selectionController_;},filter:function(filterExpression){var result=new TQuery(this.selectionController_);result.parent_=this;result.filterExpression_=tv.e.tquery.Filter.normalizeFilterExpression(filterExpression);return result;},createFilterTaskGraph_:function(){var nodes=[];var node=this;while(node!==undefined){nodes.push(node);node=node.parent_;}
-var rootTask=new tv.b.Task();var lastTask=rootTask;for(var i=nodes.length-1;i>=0;i--){var node=nodes[i];if(node.selection_!==undefined)
-continue;node.selection_=new tv.c.Selection();if(node.parent_===undefined){lastTask=lastTask.after(this.selectEverythingAsTask_(node.selection_));}else{var prevNode=nodes[i+1];lastTask=this.createFilterTaskForNode_(lastTask,node,prevNode);}}
-return{rootTask:rootTask,lastTask:lastTask,lastNode:node};},createFilterTaskForNode_:function(lastTask,node,prevNode){return lastTask.after(function(){node.evaluateFilterExpression_(prevNode.selection_,node.selection_);},this);},evaluateFilterExpression_:function(inputSelection,outputSelection){var seenEvents={};inputSelection.forEach(function(event){var context=new tv.e.tquery.Context();context.event=event;this.evaluateFilterExpressionForEvent_(context,inputSelection,outputSelection,seenEvents);}.bind(this));},evaluateFilterExpressionForEvent_:function(context,inputSelection,outputSelection,seenEvents){var event=context.event;if(inputSelection.contains(event)&&!seenEvents[event.guid]){seenEvents[event.guid]=true;if(!this.filterExpression_||this.filterExpression_.evaluate(context))
+return true;return this.subExpression.evaluate(context);}};tr.c.ScriptingObjectRegistry.register(function(subExpression){return new FilterIsTopLevel(subExpression);},{name:'isTopLevel'});return{FilterIsTopLevel:FilterIsTopLevel};});'use strict';tr.exportTo('tr.e.tquery',function(){function TQuery(selectionController){tr.c.ScriptingObject.call(this);this.selectionController_=selectionController;this.parent_=undefined;this.filterExpression_=undefined;this.selection_=undefined;};TQuery.prototype={__proto__:tr.c.ScriptingObject.prototype,onModelChanged:function(){this.selection_=undefined;},get selectionController(){return this.selectionController_;},filter:function(filterExpression){var result=new TQuery(this.selectionController_);result.parent_=this;result.filterExpression_=tr.e.tquery.Filter.normalizeFilterExpression(filterExpression);return result;},createFilterTaskGraph_:function(){var nodes=[];var node=this;while(node!==undefined){nodes.push(node);node=node.parent_;}
+var rootTask=new tr.b.Task();var lastTask=rootTask;for(var i=nodes.length-1;i>=0;i--){var node=nodes[i];if(node.selection_!==undefined)
+continue;node.selection_=new tr.c.Selection();if(node.parent_===undefined){lastTask=lastTask.after(this.selectEverythingAsTask_(node.selection_));}else{var prevNode=nodes[i+1];lastTask=this.createFilterTaskForNode_(lastTask,node,prevNode);}}
+return{rootTask:rootTask,lastTask:lastTask,lastNode:node};},createFilterTaskForNode_:function(lastTask,node,prevNode){return lastTask.after(function(){node.evaluateFilterExpression_(prevNode.selection_,node.selection_);},this);},evaluateFilterExpression_:function(inputSelection,outputSelection){var seenEvents={};inputSelection.forEach(function(event){var context=new tr.e.tquery.Context();context.event=event;this.evaluateFilterExpressionForEvent_(context,inputSelection,outputSelection,seenEvents);}.bind(this));},evaluateFilterExpressionForEvent_:function(context,inputSelection,outputSelection,seenEvents){var event=context.event;if(inputSelection.contains(event)&&!seenEvents[event.guid]){seenEvents[event.guid]=true;if(!this.filterExpression_||this.filterExpression_.evaluate(context))
 outputSelection.push(event);}
 if(!event.subSlices)
-return;context=context.push(event);for(var i=0;i<event.subSlices.length;i++){context.event=event.subSlices[i];this.evaluateFilterExpressionForEvent_(context,inputSelection,outputSelection,seenEvents);}},show:function(){var graph=this.createFilterTaskGraph_();graph.lastTask=graph.lastTask.after(function(){this.selectionController.showScriptControlSelection(graph.lastNode.selection_);},this);return graph.rootTask;},selectEverythingAsTask_:function(selection){var passThroughFilter=new tv.c.Filter();var filterTask=this.selectionController.addAllEventsMatchingFilterToSelectionAsTask(passThroughFilter,selection);return filterTask;},get selection(){if(this.selection_===undefined){var graph=this.createFilterTaskGraph_();tv.b.Task.RunSynchronously(graph.rootTask);}
-return this.selection_;}};tv.c.ScriptingObjectRegistry.register(new TQuery(),{name:'$t'});return{TQuery:TQuery};});'use strict';Polymer('tracing-scripting-control',{_isEnterKey:function(event){return event.keyCode!==229&&event.keyIdentifier==='Enter';},_setFocused:function(focused){var promptEl=this.$.prompt;if(focused){promptEl.focus();this.$.root.classList.add('focused');if(promptEl.innerText.length>0){var sel=window.getSelection();sel.collapse(promptEl.firstChild,promptEl.innerText.length);}}else{promptEl.blur();this.$.root.classList.remove('focused');var parent=promptEl.parentElement;var nextEl=promptEl.nextSibling;promptEl.remove();parent.insertBefore(promptEl,nextEl);}},onConsoleFocus:function(e){e.stopPropagation();this._setFocused(true);},onConsoleBlur:function(e){e.stopPropagation();this._setFocused(false);},promptKeyDown:function(e){e.stopPropagation();if(!this._isEnterKey(e))
+return;context=context.push(event);for(var i=0;i<event.subSlices.length;i++){context.event=event.subSlices[i];this.evaluateFilterExpressionForEvent_(context,inputSelection,outputSelection,seenEvents);}},show:function(){var graph=this.createFilterTaskGraph_();graph.lastTask=graph.lastTask.after(function(){this.selectionController.showScriptControlSelection(graph.lastNode.selection_);},this);return graph.rootTask;},selectEverythingAsTask_:function(selection){var passThroughFilter=new tr.c.Filter();var filterTask=this.selectionController.addAllEventsMatchingFilterToSelectionAsTask(passThroughFilter,selection);return filterTask;},get selection(){if(this.selection_===undefined){var graph=this.createFilterTaskGraph_();tr.b.Task.RunSynchronously(graph.rootTask);}
+return this.selection_;}};tr.c.ScriptingObjectRegistry.register(new TQuery(),{name:'$t'});return{TQuery:TQuery};});'use strict';Polymer('tracing-scripting-control',{_isEnterKey:function(event){return event.keyCode!==229&&event.keyIdentifier==='Enter';},_setFocused:function(focused){var promptEl=this.$.prompt;if(focused){promptEl.focus();this.$.root.classList.add('focused');if(promptEl.innerText.length>0){var sel=window.getSelection();sel.collapse(promptEl.firstChild,promptEl.innerText.length);}}else{promptEl.blur();this.$.root.classList.remove('focused');var parent=promptEl.parentElement;var nextEl=promptEl.nextSibling;promptEl.remove();parent.insertBefore(promptEl,nextEl);}},onConsoleFocus:function(e){e.stopPropagation();this._setFocused(true);},onConsoleBlur:function(e){e.stopPropagation();this._setFocused(false);},promptKeyDown:function(e){e.stopPropagation();if(!this._isEnterKey(e))
 return;var promptEl=this.$.prompt;var command=promptEl.innerText;if(command.length===0)
 return;promptEl.innerText='';this.addLine_(String.fromCharCode(187)+' '+command);try{var result=this.controller_.executeCommand(command);}catch(e){result=e.stack||e.stackTrace;}
-if(result instanceof tv.b.Task){tv.b.Task.RunWhenIdle(result);}else{this.addLine_(result);}},addLine_:function(line){var historyEl=this.$.history;if(historyEl.innerText.length!==0)
-historyEl.innerText+='\n';historyEl.innerText+=line;},promptKeyPress:function(e){e.stopPropagation();},toggleVisibility:function(){var root=this.$.root;if(!this.visible){root.classList.remove('hidden');this._setFocused(true);}else{root.classList.add('hidden');this._setFocused(false);}},get hasFocus(){return this===document.activeElement;},get visible(){var root=this.$.root;return!root.classList.contains('hidden');},get controller(){return this.controller_;},set controller(c){this.controller_=c;}});'use strict';Polymer('tv-c-side-panel',{ready:function(){this.objectInstance_=undefined;},get rangeOfInterest(){throw new Error('Not implemented');},set rangeOfInterest(rangeOfInterest){throw new Error('Not implemented');},get selection(){throw new Error('Not implemented');},set selection(selection){throw new Error('Not implemented');},get model(){throw new Error('Not implemented');},set model(model){throw new Error('Not implemented');},get listeningToKeys(){throw new Error('Not implemented');}});'use strict';Polymer('tv-c-side-panel-container',{ready:function(){this.activePanelContainer_=this.$.active_panel_container;this.tabStrip_=this.$.tab_strip;this.rangeOfInterest_=new tv.b.Range();this.selectionController_=undefined;this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.onModelChanged_=this.onModelChanged_.bind(this);},get selectionController(){return this.selectionController_;},set selectionController(selectionController){if(this.selectionController){this.selectionController_.removeEventListener('change',this.onSelectionChanged_);this.selectionController_.removeEventListener('model-changed',this.onModelChanged_);}
+if(result instanceof tr.b.Task){tr.b.Task.RunWhenIdle(result);}else{this.addLine_(result);}},addLine_:function(line){var historyEl=this.$.history;if(historyEl.innerText.length!==0)
+historyEl.innerText+='\n';historyEl.innerText+=line;},promptKeyPress:function(e){e.stopPropagation();},toggleVisibility:function(){var root=this.$.root;if(!this.visible){root.classList.remove('hidden');this._setFocused(true);}else{root.classList.add('hidden');this._setFocused(false);}},get hasFocus(){return this===document.activeElement;},get visible(){var root=this.$.root;return!root.classList.contains('hidden');},get controller(){return this.controller_;},set controller(c){this.controller_=c;}});'use strict';Polymer('tr-c-side-panel',{ready:function(){this.objectInstance_=undefined;},get rangeOfInterest(){throw new Error('Not implemented');},set rangeOfInterest(rangeOfInterest){throw new Error('Not implemented');},get selection(){throw new Error('Not implemented');},set selection(selection){throw new Error('Not implemented');},get model(){throw new Error('Not implemented');},set model(model){throw new Error('Not implemented');},get listeningToKeys(){throw new Error('Not implemented');},supportsModel:function(m){throw new Error('Not implemented');}});'use strict';Polymer('tr-c-side-panel-container',{ready:function(){this.activePanelContainer_=this.$.active_panel_container;this.tabStrip_=this.$.tab_strip;this.rangeOfInterest_=new tr.b.Range();this.selectionController_=undefined;this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.onModelChanged_=this.onModelChanged_.bind(this);},get selectionController(){return this.selectionController_;},set selectionController(selectionController){if(this.selectionController){this.selectionController_.removeEventListener('change',this.onSelectionChanged_);this.selectionController_.removeEventListener('model-changed',this.onModelChanged_);}
 this.selectionController_=selectionController;if(this.selectionController){this.selectionController_.addEventListener('change',this.onSelectionChanged_);this.selectionController_.addEventListener('model-changed',this.onModelChanged_);}},get selection(){return this.selectionController_.selection;},onSelectionChanged_:function(){if(this.activePanel)
 this.activePanel.selection=this.selection;},get model(){return this.selectionController_.model;},onModelChanged_:function(){this.activePanelType_=undefined;this.updateContents_();},get expanded(){this.hasAttribute('expanded');},get activePanel(){if(this.activePanelContainer_.children.length===0)
 return undefined;return this.activePanelContainer_.children[0];},get activePanelType(){return this.activePanelType_;},set activePanelType(panelType){if(this.model===undefined)
@@ -3632,32 +3704,34 @@
 this.getLabelElementForPanelType_(panelType).setAttribute('selected',true);this.setAttribute('expanded',true);this.activePanelContainer_.appendChild(panel);panel.rangeOfInterest=this.rangeOfInterest_;panel.selection=this.selection_;panel.model=this.model;this.activePanelType_=panelType;},getPanelTypeForConstructor_:function(constructor){for(var i=0;i<this.tabStrip_.children.length;i++){if(this.tabStrip_.children[i].panelType.constructor==constructor)
 return this.tabStrip_.children[i].panelType;}},getLabelElementForPanelType_:function(panelType){for(var i=0;i<this.tabStrip_.children.length;i++){if(this.tabStrip_.children[i].panelType==panelType)
 return this.tabStrip_.children[i];}
-return undefined;},updateContents_:function(){var previouslyActivePanelType=this.activePanelType;this.tabStrip_.textContent='';var supportedPanelTypes=[];var panelTypes=tv.b.getPolymerElementsThatSubclass('tv-c-side-panel');panelTypes.forEach(function(panelType){var labelEl=document.createElement('tab-strip-label');var panel=document.createElement(panelType);labelEl.textContent=panel.textLabel;labelEl.panelType=panelType;var supported=panel.supportsModel(this.model);if(this.model&&supported.supported){supportedPanelTypes.push(panelType);labelEl.setAttribute('enabled',true);labelEl.addEventListener('click',function(){this.activePanelType=this.activePanelType===panelType?undefined:panelType;}.bind(this));}else{labelEl.title='Not supported for the current trace: '+
+return undefined;},updateContents_:function(){var previouslyActivePanelType=this.activePanelType;this.tabStrip_.textContent='';var supportedPanelTypes=[];var panelTypes=tr.b.getPolymerElementsThatSubclass('tr-c-side-panel');panelTypes.forEach(function(panelType){var labelEl=document.createElement('tab-strip-label');var panel=document.createElement(panelType);labelEl.textContent=panel.textLabel;labelEl.panelType=panelType;var supported=panel.supportsModel(this.model);if(this.model&&supported.supported){supportedPanelTypes.push(panelType);labelEl.setAttribute('enabled',true);labelEl.addEventListener('click',function(){this.activePanelType=this.activePanelType===panelType?undefined:panelType;}.bind(this));}else{labelEl.title='Not supported for the current trace: '+
 supported.reason;labelEl.style.display='none';}
 this.tabStrip_.appendChild(labelEl);},this);if(previouslyActivePanelType&&supportedPanelTypes.indexOf(previouslyActivePanelType)!=-1){this.activePanelType=previouslyActivePanelType;this.setAttribute('expanded',true);}else{this.activePanelContainer_.textContent='';this.removeAttribute('expanded');}},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){if(range==undefined)
 throw new Error('Must not be undefined');this.rangeOfInterest_=range;if(this.activePanel)
-this.activePanel.rangeOfInterest=range;}});'use strict';tv.exportTo('tv.c',function(){var THIS_DOC=document.currentScript.ownerDocument;var TimelineView=tv.b.ui.define('x-timeline-view');TimelineView.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){var node=tv.b.instantiateTemplate('#timeline-view-template',THIS_DOC);this.appendChild(node);this.titleEl_=this.querySelector('.title');this.leftControlsEl_=this.querySelector('#left-controls');this.rightControlsEl_=this.querySelector('#right-controls');this.collapsingControlsEl_=this.querySelector('#collapsing-controls');this.sidePanelContainer_=this.querySelector('tv-c-side-panel-container');this.trackViewContainer_=this.querySelector('track-view-container');this.selectionController_=new tv.c.SelectionController(this);this.selectionController_.historyEnabled=true;this.findCtl_=new TracingFindControl();this.findCtl_.controller=new tv.c.FindController(this.selectionController_);this.findCtl_.addEventListener('keydown',function(e){if(e.keyCode===27){this.focus();e.preventDefault();}}.bind(this));this.scriptingCtl_=new TracingScriptingControl();this.scriptingCtl_.controller=new tv.c.ScriptingController(this.selectionController_);this.sidePanelContainer_.selectionController=this.selectionController_;this.optionsDropdown_=document.createElement('tv-b-dropdown');this.optionsDropdown_.iconElement.textContent='View Options';this.showFlowEvents_=false;this.optionsDropdown_.appendChild(tv.b.ui.createCheckBox(this,'showFlowEvents','tv.c.TimelineView.showFlowEvents',false,'Flow events'));this.highlightVSync_=false;this.highlightVSyncCheckbox_=tv.b.ui.createCheckBox(this,'highlightVSync','tv.c.TimelineView.highlightVSync',false,'Highlight VSync');this.optionsDropdown_.appendChild(this.highlightVSyncCheckbox_);this.rightControls.appendChild(this.createMetadataButton_());this.rightControls.appendChild(this.optionsDropdown_);this.rightControls.appendChild(this.findCtl_);this.rightControls.appendChild(this.createConsoleButton_());this.rightControls.appendChild(this.createHelpButton_());this.collapsingControls.appendChild(this.scriptingCtl_);this.dragEl_=this.querySelector('x-drag-handle');tv.b.ui.decorate(this.dragEl_,tv.b.ui.DragHandle);this.analysisEl_=this.querySelector('#analysis');this.analysisEl_.selectionController=this.selectionController_;this.addEventListener('requestSelectionChange',function(e){var sc=this.selectionController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);document.addEventListener('keydown',this.onKeyDown_.bind(this),true);document.addEventListener('keypress',this.onKeypress_.bind(this),true);this.dragEl_.target=this.analysisEl_;},updateDocumentFavicon:function(){var hue;if(!this.model)
+this.activePanel.rangeOfInterest=range;}});'use strict';tr.exportTo('tr.c',function(){var THIS_DOC=document.currentScript.ownerDocument;var TimelineView=tr.b.ui.define('x-timeline-view');TimelineView.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){var node=tr.b.instantiateTemplate('#timeline-view-template',THIS_DOC);this.appendChild(node);this.titleEl_=this.querySelector('.title');this.leftControlsEl_=this.querySelector('#left-controls');this.rightControlsEl_=this.querySelector('#right-controls');this.collapsingControlsEl_=this.querySelector('#collapsing-controls');this.sidePanelContainer_=this.querySelector('tr-c-side-panel-container');this.trackViewContainer_=this.querySelector('track-view-container');this.selectionController_=new tr.c.SelectionController(this);this.selectionController_.historyEnabled=true;this.findCtl_=new TracingFindControl();this.findCtl_.controller=new tr.c.FindController(this.selectionController_);this.findCtl_.addEventListener('keydown',function(e){if(e.keyCode===27){this.focus();e.preventDefault();}}.bind(this));this.scriptingCtl_=new TracingScriptingControl();this.scriptingCtl_.controller=new tr.c.ScriptingController(this.selectionController_);this.sidePanelContainer_.selectionController=this.selectionController_;if(window.tr.e&&window.tr.e.rail&&window.tr.e.rail.RAILScore){this.railScoreSpan_=document.createElement('tr-e-rail-rail-score-span');this.rightControls.appendChild(this.railScoreSpan_);}else{this.railScoreSpan_=undefined;}
+this.optionsDropdown_=document.createElement('tr-b-ui-dropdown');this.optionsDropdown_.iconElement.textContent='View Options';this.showFlowEvents_=false;this.optionsDropdown_.appendChild(tr.b.ui.createCheckBox(this,'showFlowEvents','tr.c.TimelineView.showFlowEvents',false,'Flow events'));this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.b.ui.createCheckBox(this,'highlightVSync','tr.c.TimelineView.highlightVSync',false,'Highlight VSync');this.optionsDropdown_.appendChild(this.highlightVSyncCheckbox_);this.rightControls.appendChild(this.createMetadataButton_());this.rightControls.appendChild(this.optionsDropdown_);this.rightControls.appendChild(this.findCtl_);this.rightControls.appendChild(this.createConsoleButton_());this.rightControls.appendChild(this.createHelpButton_());this.collapsingControls.appendChild(this.scriptingCtl_);this.dragEl_=this.querySelector('x-drag-handle');tr.b.ui.decorate(this.dragEl_,tr.b.ui.DragHandle);this.analysisEl_=this.querySelector('#analysis');this.analysisEl_.selectionController=this.selectionController_;this.addEventListener('requestSelectionChange',function(e){var sc=this.selectionController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);document.addEventListener('keydown',this.onKeyDown_.bind(this),true);document.addEventListener('keypress',this.onKeypress_.bind(this),true);this.dragEl_.target=this.analysisEl_;},updateDocumentFavicon:function(){var hue;if(!this.model)
 hue='blue';else
-hue=this.model.faviconHue;var faviconData=tv.c.FaviconsByHue[hue];if(faviconData===undefined)
-faviconData=tv.c.FaviconsByHue['blue'];var link=document.head.querySelector('link[rel="shortcut icon"]');if(!link){link=document.createElement('link');link.rel='shortcut icon';document.head.appendChild(link);}
+hue=this.model.faviconHue;var faviconData=tr.c.FaviconsByHue[hue];if(faviconData===undefined)
+faviconData=tr.c.FaviconsByHue['blue'];var link=document.head.querySelector('link[rel="shortcut icon"]');if(!link){link=document.createElement('link');link.rel='shortcut icon';document.head.appendChild(link);}
 link.href=faviconData;},get showFlowEvents(){return this.showFlowEvents_;},set showFlowEvents(showFlowEvents){this.showFlowEvents_=showFlowEvents;if(!this.trackView_)
 return;this.trackView_.viewport.showFlowEvents=showFlowEvents;},get highlightVSync(){return this.highlightVSync_;},set highlightVSync(highlightVSync){this.highlightVSync_=highlightVSync;if(!this.trackView_)
-return;this.trackView_.viewport.highlightVSync=highlightVSync;},createHelpButton_:function(){var node=tv.b.instantiateTemplate('#help-btn-template',THIS_DOC);var showEl=node.querySelector('.view-help-button');var helpTextEl=node.querySelector('.view-help-text');var dlg=new tv.b.ui.Overlay();dlg.title='chrome://tracing Help';dlg.classList.add('view-help-overlay');dlg.appendChild(node);function onClick(e){dlg.visible=!dlg.visible;var mod=tv.isMac?'cmd ':'ctrl';var spans=helpTextEl.querySelectorAll('span.mod');for(var i=0;i<spans.length;i++){spans[i].textContent=mod;}
+return;this.trackView_.viewport.highlightVSync=highlightVSync;},createHelpButton_:function(){var node=tr.b.instantiateTemplate('#help-btn-template',THIS_DOC);var showEl=node.querySelector('.view-help-button');var helpTextEl=node.querySelector('.view-help-text');var dlg=new tr.b.ui.Overlay();dlg.title='chrome://tracing Help';dlg.classList.add('view-help-overlay');dlg.appendChild(node);function onClick(e){dlg.visible=!dlg.visible;var mod=tr.isMac?'cmd ':'ctrl';var spans=helpTextEl.querySelectorAll('span.mod');for(var i=0;i<spans.length;i++){spans[i].textContent=mod;}
 e.stopPropagation();return false;}
-showEl.addEventListener('click',onClick.bind(this));return showEl;},createConsoleButton_:function(){var node=tv.b.instantiateTemplate('#console-btn-template',THIS_DOC);var toggleEl=node.querySelector('.view-console-button');function onClick(e){this.scriptingCtl_.toggleVisibility();e.stopPropagation();return false;}
-toggleEl.addEventListener('click',onClick.bind(this));return toggleEl;},createMetadataButton_:function(){var node=tv.b.instantiateTemplate('#metadata-btn-template',THIS_DOC);var showEl=node.querySelector('.view-metadata-button');var textEl=node.querySelector('.info-button-text');var dlg=new tv.b.ui.Overlay();dlg.title='Metadata for trace';dlg.classList.add('view-metadata-overlay');dlg.appendChild(node);function onClick(e){dlg.visible=true;var metadataStrings=[];var model=this.model;for(var data in model.metadata){var meta=model.metadata[data];var name=JSON.stringify(meta.name);var value=JSON.stringify(meta.value,undefined,' ');metadataStrings.push(name+': '+value);}
+showEl.addEventListener('click',onClick.bind(this));return showEl;},createConsoleButton_:function(){var node=tr.b.instantiateTemplate('#console-btn-template',THIS_DOC);var toggleEl=node.querySelector('.view-console-button');function onClick(e){this.scriptingCtl_.toggleVisibility();e.stopPropagation();return false;}
+toggleEl.addEventListener('click',onClick.bind(this));return toggleEl;},createMetadataButton_:function(){var node=tr.b.instantiateTemplate('#metadata-btn-template',THIS_DOC);var showEl=node.querySelector('.view-metadata-button');var textEl=node.querySelector('.info-button-text');var dlg=new tr.b.ui.Overlay();dlg.title='Metadata for trace';dlg.classList.add('view-metadata-overlay');dlg.appendChild(node);function onClick(e){dlg.visible=true;var metadataStrings=[];var model=this.model;for(var data in model.metadata){var meta=model.metadata[data];var name=JSON.stringify(meta.name);var value=JSON.stringify(meta.value,undefined,' ');metadataStrings.push(name+': '+value);}
 textEl.textContent=metadataStrings.join('\n');e.stopPropagation();return false;}
 showEl.addEventListener('click',onClick.bind(this));function updateVisibility(){showEl.style.display=(this.model&&this.model.metadata.length)?'':'none';}
 var updateVisibility_=updateVisibility.bind(this);updateVisibility_();this.addEventListener('modelChange',updateVisibility_);return showEl;},get leftControls(){return this.leftControlsEl_;},get rightControls(){return this.rightControlsEl_;},get collapsingControls(){return this.collapsingControlsEl_;},get viewTitle(){return this.titleEl_.textContent.substring(this.titleEl_.textContent.length-2);},set viewTitle(text){if(text===undefined){this.titleEl_.textContent='';this.titleEl_.hidden=true;return;}
 this.titleEl_.hidden=false;this.titleEl_.textContent=text;},get model(){if(this.trackView_)
-return this.trackView_.model;return undefined;},set model(model){var modelInstanceChanged=model!=this.model;var modelValid=model&&!model.bounds.isEmpty;if(modelInstanceChanged){this.trackViewContainer_.textContent='';if(this.trackView_){this.trackView_.viewport.removeEventListener('change',this.onViewportChanged_);this.trackView_.selectionController=undefined;this.trackView_.detach();this.trackView_=undefined;}
+return this.trackView_.model;return undefined;},set model(model){var modelInstanceChanged=model!=this.model;var modelValid=model&&!model.bounds.isEmpty;if(modelInstanceChanged){if(this.railScoreSpan_)
+this.railScoreSpan_.railScore=undefined;this.trackViewContainer_.textContent='';if(this.trackView_){this.trackView_.viewport.removeEventListener('change',this.onViewportChanged_);this.trackView_.selectionController=undefined;this.trackView_.detach();this.trackView_=undefined;}
 this.selectionController_.modelWillChange();}
-if(modelValid&&!this.trackView_){this.trackView_=new tv.c.TimelineTrackView(this);this.trackView.selectionController=this.selectionController_;this.trackView_.focusElement=this.focusElement_?this.focusElement_:this.parentElement;this.trackViewContainer_.appendChild(this.trackView_);this.trackView_.viewport.addEventListener('change',this.onViewportChanged_);}
-if(modelValid){this.trackView_.model=model;this.trackView_.viewport.showFlowEvents=this.showFlowEvents;this.trackView_.viewport.highlightVSync=this.highlightVSync;}
-if(modelInstanceChanged){tv.b.dispatchSimpleEvent(this,'modelChange');this.selectionController_.modelDidChange();this.onViewportChanged_();}},get selectionController(){return this.selectionController_;},get trackView(){return this.trackView_;},get settings(){if(!this.settings_)
-this.settings_=new tv.b.Settings();return this.settings_;},set focusElement(value){this.focusElement_=value;if(this.trackView_)
+if(modelValid&&!this.trackView_){this.trackView_=new tr.c.TimelineTrackView(this);this.trackView.selectionController=this.selectionController_;this.trackView_.focusElement=this.focusElement_?this.focusElement_:this.parentElement;this.trackViewContainer_.appendChild(this.trackView_);this.trackView_.viewport.addEventListener('change',this.onViewportChanged_);}
+if(modelValid){this.trackView_.model=model;this.trackView_.viewport.showFlowEvents=this.showFlowEvents;this.trackView_.viewport.highlightVSync=this.highlightVSync;if(this.railScoreSpan_){var railScore=tr.e.rail.RAILScore.fromModel(model);this.railScoreSpan_.railScore=railScore;}}
+if(modelInstanceChanged){tr.b.dispatchSimpleEvent(this,'modelChange');this.selectionController_.modelDidChange();this.onViewportChanged_();}},get selectionController(){return this.selectionController_;},get trackView(){return this.trackView_;},get settings(){if(!this.settings_)
+this.settings_=new tr.b.Settings();return this.settings_;},set focusElement(value){this.focusElement_=value;if(this.trackView_)
 this.trackView_.focusElement=value;},get focusElement(){if(this.focusElement_)
-return this.focusElement_;return this.parentElement;},get listenToKeys_(){if(!tv.b.ui.isElementAttachedToDocument(this))
+return this.focusElement_;return this.parentElement;},get listenToKeys_(){if(!tr.b.ui.isElementAttachedToDocument(this))
 return;if(document.activeElement.type==='textarea')
 return false;if(this.sidePanelContainer_.activePanel&&this.sidePanelContainer_.activePanel.listeningToKeys)
 return false;if(!this.focusElement_)
@@ -3673,30 +3747,30 @@
 if(this.findCtl_.hasFocus)
 return;switch(e.keyCode){case'v'.charCodeAt(0):this.toggleHighlightVSync_();e.preventDefault();break;}},onViewportChanged_:function(e){var spc=this.sidePanelContainer_;if(!this.trackView_){spc.rangeOfInterest.reset();return;}
 var vr=this.trackView_.viewport.interestRange.asRangeObject();if(!spc.rangeOfInterest.equals(vr))
-spc.rangeOfInterest=vr;},toggleHighlightVSync_:function(){this.highlightVSyncCheckbox_.checked=!this.highlightVSyncCheckbox_.checked;},setFindCtlText:function(string){this.findCtl_.setText(string);}};return{TimelineView:TimelineView};});'use strict';tv.exportTo('tv',function(){var TraceViewer=tv.b.ui.define('trace-viewer',tv.c.TimelineView);TraceViewer.prototype={__proto__:tv.c.TimelineView.prototype,decorate:function(opt_url){tv.c.TimelineView.prototype.decorate.call(this);if(opt_url===undefined)
+spc.rangeOfInterest=vr;},toggleHighlightVSync_:function(){this.highlightVSyncCheckbox_.checked=!this.highlightVSyncCheckbox_.checked;},setFindCtlText:function(string){this.findCtl_.setText(string);}};return{TimelineView:TimelineView};});'use strict';tr.exportTo('tr',function(){var TraceViewer=tr.b.ui.define('trace-viewer',tr.c.TimelineView);TraceViewer.prototype={__proto__:tr.c.TimelineView.prototype,decorate:function(opt_url){tr.c.TimelineView.prototype.decorate.call(this);if(opt_url===undefined)
 return;var url=opt_url;var that=this;var req=new XMLHttpRequest();var is_binary=/[.]gz$/.test(url)||/[.]zip$/.test(url);req.overrideMimeType('text/plain; charset=x-user-defined');req.open('GET',url,true);if(is_binary)
-req.responseType='arraybuffer';req.onreadystatechange=function(aEvt){if(req.readyState==4){window.setTimeout(function(){if(req.status==200){onResult(is_binary?req.response:req.responseText);}else{onResultFail(req.status);}},0);}};req.send(null);function onResultFail(err){var overlay=new tv.b.ui.Overlay();overlay.textContent=err+': '+url+' could not be loaded';overlay.title='Failed to fetch data';overlay.visible=true;}
-var model;function onResult(result){model=new tv.c.TraceModel();var p=model.importTracesWithProgressDialog([result],true);p.then(onModelLoaded,onImportFail);}
+req.responseType='arraybuffer';req.onreadystatechange=function(aEvt){if(req.readyState==4){window.setTimeout(function(){if(req.status==200){onResult(is_binary?req.response:req.responseText);}else{onResultFail(req.status);}},0);}};req.send(null);function onResultFail(err){var overlay=new tr.b.ui.Overlay();overlay.textContent=err+': '+url+' could not be loaded';overlay.title='Failed to fetch data';overlay.visible=true;}
+var model;function onResult(result){model=new tr.Model();var p=model.importTracesWithProgressDialog([result],true);p.then(onModelLoaded,onImportFail);}
 function onModelLoaded(){that.model=model;that.viewTitle=url;if(that.timeline)
 that.timeline.focusElement=that;}
-function onImportFail(){var overlay=new tv.b.ui.Overlay();overlay.textContent=tv.b.normalizeException(err).message;overlay.title='Import error';overlay.visible=true;}}};return{TraceViewer:TraceViewer};});'use strict';tv.exportTo('tv.e.importer.battor',function(){var Importer=tv.c.importer.Importer;function BattorImporter(model,events){this.importPriority=3;this.series_=undefined;this.sampleRate_=undefined;this.model_=model;this.events_=events;this.kernelThreadStates_={};this.lines_=[];this.pseudoThreadCounter=1;}
-var TestExports={};var battorLineRE=/^(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)$/;var sampleRateLineRE=/^# sample_rate=(\d+)Hz/;BattorImporter.canImport=function(events){if(!(typeof(events)==='string'||events instanceof String))
-return false;if(/^# BattOr/.test(events))
-return true;return false;};BattorImporter.prototype={__proto__:Importer.prototype,get model(){return this.model_;},importEvents:function(isSecondaryImport){var name='power';var series=new tv.c.trace_model.CounterSeries('value',tv.b.ui.getColorIdForGeneralPurposeString(name+'.'+'value'));this.importPowerSamples(series);this.series_=series;var syncMarks=this.model_.getClockSyncRecordsNamed('battor');if(syncMarks.length<2){this.model_.importWarning({type:'clock_sync',message:'Cannot import BattOr measurments without a sync signal.'});return;}
-var syncCtr=this.model_.kernel.counters['null.vreg '+syncMarks[0].args['regulator']+' enabled'];if(syncCtr===undefined){this.model_.importWarning({type:'clock_sync',message:'Cannot import BattOr power trace without sync vreg.'});return;}
+function onImportFail(){var overlay=new tr.b.ui.Overlay();overlay.textContent=tr.b.normalizeException(err).message;overlay.title='Import error';overlay.visible=true;}}};return{TraceViewer:TraceViewer};});'use strict';tr.exportTo('tr.e.importer.battor',function(){var Importer=tr.importer.Importer;function BattorImporter(model,events){this.importPriority=3;this.sampleRate_=undefined;this.model_=model;this.events_=events;}
+var TestExports={};var battorDataLineRE=/^(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)$/;var battorHeaderLineRE=/^# BattOr/;var sampleRateLineRE=/^# sample_rate=(\d+)Hz/;BattorImporter.canImport=function(events){if(!(typeof(events)==='string'||events instanceof String))
+return false;return battorHeaderLineRE.test(events);};BattorImporter.prototype={__proto__:Importer.prototype,get model(){return this.model_;},importEvents:function(isSecondaryImport){var name='power';var series=new tr.model.CounterSeries('value',tr.b.ui.getColorIdForGeneralPurposeString(name+'.'+'value'));this.importPowerSamples(series);var syncMarks=this.model_.getClockSyncRecordsNamed('battor');if(syncMarks.length<1){this.model_.importWarning({type:'clock_sync',message:'Cannot import BattOr power trace without a sync signal.'});return;}
+var shiftTs=this.correlationClockSync(syncMarks,series);if(shiftTs===undefined){this.model_.importWarning({type:'clock_sync',message:'All of the BattOr power trace clock sync techinques failed.'});return;}
+var ctr=this.model_.kernel.getOrCreateCounter(null,'Power');if(ctr.numSeries===0){ctr.addSeries(series);}
+ctr.shiftTimestampsForward(shiftTs);},importPowerSamples:function(series){var lines=this.events_.split('\n');this.model_.updateBounds();var minTs=0;if(this.model_.bounds.min!==undefined)
+minTs=this.model_.bounds.min;lines.forEach(function(line){if(line.length===0)
+return;if(/^#/.test(line)){groups=sampleRateLineRE.exec(line);if(!groups)
+return;this.sampleRate_=parseInt(groups[1]);}else{var groups=battorDataLineRE.exec(line);if(!groups){this.model_.importWarning({type:'parse_error',message:'Unrecognized line: '+line});return;}
+var time=parseFloat(groups[1])+minTs;var voltage_mV=parseFloat(groups[2]);var current_mA=parseFloat(groups[3]);series.addCounterSample(time,(voltage_mV*current_mA)/1000);}},this);},correlationClockSync:function(syncMarks,series){var syncCtr=this.model_.kernel.counters['null.vreg '+syncMarks[0].args['regulator']+' enabled'];if(syncCtr===undefined){this.model_.importWarning({type:'clock_sync',message:'Cannot correlate BattOr power trace without sync vreg.'});return undefined;}
 var syncEvents=[];var firstSyncEventTs=undefined;syncCtr.series[0].iterateAllEvents(function(event){if(event.timestamp>=syncMarks[0].ts&&event.timestamp<=syncMarks[1].ts){if(firstSyncEventTs===undefined)
 firstSyncEventTs=event.timestamp;var newEvent={'ts':(event.timestamp-firstSyncEventTs)/1000,'val':event.value};syncEvents.push(newEvent);}});var syncSamples=[];var syncNumSamples=Math.ceil(syncEvents[syncEvents.length-1].ts*this.sampleRate_);for(var i=1;i<syncEvents.length;i++){var sampleStartIdx=Math.ceil(syncEvents[i-1].ts*this.sampleRate_);var sampleEndIdx=Math.ceil(syncEvents[i].ts*this.sampleRate_);for(var j=sampleStartIdx;j<sampleEndIdx;j++){syncSamples[j]=syncEvents[i-1].val;}}
-var powerSamples=series.samples;if(powerSamples.length<syncSamples.length){this.model_.importWarning({type:'not_enough_samples',message:'Not enough power samples to correlate with sync signal.'});return;}
+var powerSamples=series.samples;if(powerSamples.length<syncSamples.length){this.model_.importWarning({type:'not_enough_samples',message:'Not enough power samples to correlate with sync signal.'});return undefined;}
 var maxShift=powerSamples.length-syncSamples.length;var minShift=0;var corrNumSamples=this.sampleRate_*5.0;if(powerSamples.length>corrNumSamples)
 minShift=powerSamples.length-corrNumSamples;var corr=[];for(var shift=minShift;shift<=maxShift;shift++){var corrSum=0;var powerAvg=0;for(var i=0;i<syncSamples.length;i++){corrSum+=(powerSamples[i+shift].value*syncSamples[i]);powerAvg+=powerSamples[i+shift].value;}
 powerAvg=powerAvg/syncSamples.length;corr.push(corrSum/powerAvg);}
 var corrPeakIdx=0;var corrPeak=0;for(var i=0;i<powerSamples.length;i++){if(corr[i]>corrPeak){corrPeak=corr[i];corrPeakIdx=i;}}
-var ctr=this.model_.kernel.getOrCreateCounter(null,'Power');if(ctr.numSeries===0){ctr.addSeries(series);}
-this.counter_=ctr;var corrPeakTs=((minShift+corrPeakIdx)/this.sampleRate_);corrPeakTs*=1000;var syncStartTs=firstSyncEventTs-this.model_.bounds.min;var shiftTs=syncStartTs-corrPeakTs;this.counter_.shiftTimestampsForward(shiftTs);},importPowerSamples:function(series){var lines=this.events_.split('\n');this.model_.updateBounds();var minTs=0;if(this.model_.bounds.min!==undefined)
-minTs=this.model_.bounds.min;lines.forEach(function(line){if(line.length==0)
-return;if(/^#/.test(line)){groups=sampleRateLineRE.exec(line);if(!groups)
-return;this.sampleRate_=parseInt(groups[1]);}else{var groups=battorLineRE.exec(line);if(!groups){this.model_.importWarning({type:'parse_error',message:'Unrecognized line: '+line});return;}
-var time=parseFloat(groups[1])+minTs;var voltage_mV=parseFloat(groups[2]);var current_mA=parseFloat(groups[3]);series.addCounterSample(time,(voltage_mV*current_mA)/1000);}},this);}};tv.c.importer.Importer.register(BattorImporter);return{BattorImporter:BattorImporter,_BattorImporterTestExports:TestExports};});!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";c.encode=function(a){for(var b,c,e,f,g,h,i,j="",k=0;k<a.length;)b=a.charCodeAt(k++),c=a.charCodeAt(k++),e=a.charCodeAt(k++),f=b>>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)f=d.indexOf(a.charAt(k++)),g=d.indexOf(a.charAt(k++)),h=d.indexOf(a.charAt(k++)),i=d.indexOf(a.charAt(k++)),b=f<<2|g>>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.length<a||0>a)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;g<e.length;g++)h=e[g],this.file(h.fileName,h.decompressed,{binary:!0,optimizedBinaryString:!0,date:h.date,dir:h.dir,comment:h.fileComment.length?h.fileComment:null,createFolders:b.createFolders});return f.zipComment.length&&(this.comment=f.zipComment),this}},{"./base64":1,"./zipEntries":22}],11:[function(a,b){(function(a){"use strict";b.exports=function(b,c){return new a(b,c)},b.exports.test=function(b){return a.isBuffer(b)}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],12:[function(a,b){"use strict";function c(a){this.data=a,this.length=this.data.length,this.index=0}var d=a("./uint8ArrayReader");c.prototype=new d,c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./uint8ArrayReader":18}],13:[function(a,b){"use strict";var c=a("./support"),d=a("./utils"),e=a("./crc32"),f=a("./signature"),g=a("./defaults"),h=a("./base64"),i=a("./compressions"),j=a("./compressedObject"),k=a("./nodeBuffer"),l=a("./utf8"),m=a("./stringWriter"),n=a("./uint8ArrayWriter"),o=function(a){if(a._data instanceof j&&(a._data=a._data.getContent(),a.options.binary=!0,a.options.base64=!1,"uint8array"===d.getTypeOf(a._data))){var b=a._data;a._data=new Uint8Array(b.length),0!==b.length&&a._data.set(b,0)}return a._data},p=function(a){var b=o(a),e=d.getTypeOf(b);return"string"===e?!a.options.binary&&c.nodebuffer?k(b,"utf-8"):a.asBinary():b},q=function(a){var b=o(this);return null===b||"undefined"==typeof b?"":(this.options.base64&&(b=h.decode(b)),b=a&&this.options.binary?A.utf8decode(b):d.transformTo("string",b),a||this.options.binary||(b=d.transformTo("string",A.utf8encode(b))),b)},r=function(a,b,c){this.name=a,this.dir=c.dir,this.date=c.date,this.comment=c.comment,this._data=b,this.options=c,this._initialMetadata={dir:c.dir,date:c.date}};r.prototype={asText:function(){return q.call(this,!0)},asBinary:function(){return q.call(this,!1)},asNodeBuffer:function(){var a=p(this);return d.transformTo("nodebuffer",a)},asUint8Array:function(){var a=p(this);return d.transformTo("uint8array",a)},asArrayBuffer:function(){return this.asUint8Array().buffer}};var s=function(a,b){var c,d="";for(c=0;b>c;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a<arguments.length;a++)for(b in arguments[a])arguments[a].hasOwnProperty(b)&&"undefined"==typeof c[b]&&(c[b]=arguments[a][b]);return c},u=function(a){return a=a||{},a.base64!==!0||null!==a.binary&&void 0!==a.binary||(a.binary=!0),a=t(a,g),a.date=a.date||new Date,null!==a.compression&&(a.compression=a.compression.toUpperCase()),a},v=function(a,b,c){var e,f=d.getTypeOf(b);if(c=u(c),c.createFolders&&(e=w(a))&&x.call(this,e,!0),c.dir||null===b||"undefined"==typeof b)c.base64=!1,c.binary=!1,b=null;else if("string"===f)c.binary&&!c.base64&&c.optimizedBinaryString!==!0&&(b=d.string2binary(b));else{if(c.base64=!1,c.binary=!0,!(f||b instanceof j))throw new Error("The data of '"+a+"' is in an unsupported format !");"arraybuffer"===f&&(b=d.transformTo("uint8array",b))}var g=new r(a,b,c);return this.files[a]=g,g},w=function(a){"/"==a.slice(-1)&&(a=a.substring(0,a.length-1));var b=a.lastIndexOf("/");return b>0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b?b:!1,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\x00",w+=p||q?"\x00\b":"\x00\x00",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\x00"+w+s(o.length,2)+"\x00\x00\x00\x00"+(j===!0?"\x00\x00\x00":"\x00\x00\x00\x00")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d<c.length;d++)delete this.files[c[d].name];return this},generate:function(a){a=t(a||{},{base64:!0,compression:"STORE",type:"base64",comment:null}),d.checkSupport(a.type);var b,c,e=[],g=0,j=0,k=d.transformTo("string",this.utf8encode(a.comment||this.comment||""));for(var l in this.files)if(this.files.hasOwnProperty(l)){var o=this.files[l],p=o.options.compression||a.compression.toUpperCase(),q=i[p];if(!q)throw new Error(p+" is not a valid compression method !");var r=y.call(this,o,q),u=z.call(this,l,o,r,g);g+=u.fileRecord.length+r.compressedSize,j+=u.dirRecord.length,e.push(u)}var v="";v=f.CENTRAL_DIRECTORY_END+"\x00\x00\x00\x00"+s(e.length,2)+s(e.length,2)+s(j,4)+s(g,4)+s(k.length,2)+k;var w=a.type.toLowerCase();for(b="uint8array"===w||"arraybuffer"===w||"blob"===w||"nodebuffer"===w?new n(g+j+v.length):new m(g+j+v.length),c=0;c<e.length;c++)b.append(e[c].fileRecord),b.append(e[c].compressedObject.compressedContent);for(c=0;c<e.length;c++)b.append(e[c].dirRecord);b.append(v);var x=b.finalize();switch(a.type.toLowerCase()){case"uint8array":case"arraybuffer":case"nodebuffer":return d.transformTo(a.type.toLowerCase(),x);case"blob":return d.arrayBuffer2Blob(d.transformTo("arraybuffer",x));case"base64":return a.base64?h.encode(x):x;default:return x}},crc32:function(a,b){return e(a,b)},utf8encode:function(a){return d.transformTo("string",l.utf8encode(a))},utf8decode:function(a){return l.utf8decode(a)}};b.exports=A},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(a,b,c){"use strict";c.LOCAL_FILE_HEADER="PK",c.CENTRAL_FILE_HEADER="PK",c.CENTRAL_DIRECTORY_END="PK",c.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",c.ZIP64_CENTRAL_DIRECTORY_END="PK",c.DATA_DESCRIPTOR="PK\b"},{}],15:[function(a,b){"use strict";function c(a,b){this.data=a,b||(this.data=e.string2binary(this.data)),this.length=this.data.length,this.index=0}var d=a("./dataReader"),e=a("./utils");c.prototype=new d,c.prototype.byteAt=function(a){return this.data.charCodeAt(a)},c.prototype.lastIndexOfSignature=function(a){return this.data.lastIndexOf(a)},c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5,"./utils":21}],16:[function(a,b){"use strict";var c=a("./utils"),d=function(){this.data=[]};d.prototype={append:function(a){a=c.transformTo("string",a),this.data.push(a)},finalize:function(){return this.data.join("")}},b.exports=d},{"./utils":21}],17:[function(a,b,c){(function(a){"use strict";if(c.base64=!0,c.array=!0,c.string=!0,c.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,c.nodebuffer="undefined"!=typeof a,c.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)c.blob=!1;else{var b=new ArrayBuffer(0);try{c.blob=0===new Blob([b],{type:"application/zip"}).size}catch(d){try{var e=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,f=new e;f.append(b),c.blob=0===f.getBlob("application/zip").size}catch(d){c.blob=!1}}}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],18:[function(a,b){"use strict";function c(a){a&&(this.data=a,this.length=this.data.length,this.index=0)}var d=a("./dataReader");c.prototype=new d,c.prototype.byteAt=function(a){return this.data[a]},c.prototype.lastIndexOfSignature=function(a){for(var b=a.charCodeAt(0),c=a.charCodeAt(1),d=a.charCodeAt(2),e=a.charCodeAt(3),f=this.length-4;f>=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;c<a.length;++c)b[c]=255&a.charCodeAt(c);return b}function f(a){var b=65536,d=[],e=a.length,f=c.getTypeOf(a),g=0,h=!0;try{switch(f){case"uint8array":String.fromCharCode.apply(null,new Uint8Array(0));break;case"nodebuffer":String.fromCharCode.apply(null,j(0))}}catch(i){h=!1}if(!h){for(var k="",l=0;l<a.length;l++)k+=String.fromCharCode(a[l]);return k}for(;e>g&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;c<a.length;c++)b[c]=a[c];return b}var h=a("./support"),i=a("./compressions"),j=a("./nodeBuffer");c.string2binary=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(255&a.charCodeAt(c));return b},c.arrayBuffer2Blob=function(a){c.checkSupport("blob");try{return new Blob([a],{type:"application/zip"})}catch(b){try{var d=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,e=new d;return e.append(a),e.getBlob("application/zip")}catch(b){throw new Error("Bug : can't construct the Blob.")}}},c.applyFromCharCode=f;var k={};k.string={string:d,array:function(a){return e(a,new Array(a.length))},arraybuffer:function(a){return k.string.uint8array(a).buffer},uint8array:function(a){return e(a,new Uint8Array(a.length))},nodebuffer:function(a){return e(a,j(a.length))}},k.array={string:f,array:d,arraybuffer:function(a){return new Uint8Array(a).buffer},uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(a)}},k.arraybuffer={string:function(a){return f(new Uint8Array(a))},array:function(a){return g(new Uint8Array(a),new Array(a.byteLength))},arraybuffer:d,uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(new Uint8Array(a))}},k.uint8array={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return a.buffer},uint8array:d,nodebuffer:function(a){return j(a)}},k.nodebuffer={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return k.nodebuffer.uint8array(a).buffer},uint8array:function(a){return g(a,new Uint8Array(a.length))},nodebuffer:d},c.transformTo=function(a,b){if(b||(b=""),!a)return b;c.checkSupport(a);var d=c.getTypeOf(b),e=k[d][a](b);return e},c.getTypeOf=function(a){return"string"==typeof a?"string":"[object Array]"===Object.prototype.toString.call(a)?"array":h.nodebuffer&&j.test(a)?"nodebuffer":h.uint8array&&a instanceof Uint8Array?"uint8array":h.arraybuffer&&a instanceof ArrayBuffer?"arraybuffer":void 0},c.checkSupport=function(a){var b=h[a.toLowerCase()];if(!b)throw new Error(a+" is not supported by this browser")},c.MAX_VALUE_16BITS=65535,c.MAX_VALUE_32BITS=-1,c.pretty=function(a){var b,c,d="";for(c=0;c<(a||"").length;c++)b=a.charCodeAt(c),d+="\\x"+(16>b?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a<this.files.length;a++)b=this.files[a],this.reader.setIndex(b.localHeaderOffset),this.checkSignature(h.LOCAL_FILE_HEADER),b.readLocalPart(this.reader),b.handleUTF8()},readCentralDir:function(){var a;for(this.reader.setIndex(this.centralDirOffset);this.reader.readString(4)===h.CENTRAL_FILE_HEADER;)a=new i({zip64:this.zip64},this.loadOptions),a.readCentralPart(this.reader),this.files.push(a)},readEndOfCentral:function(){var a=this.reader.lastIndexOfSignature(h.CENTRAL_DIRECTORY_END);if(-1===a)throw new Error("Corrupted zip : can't find end of central directory");if(this.reader.setIndex(a),this.checkSignature(h.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===g.MAX_VALUE_16BITS||this.diskWithCentralDirStart===g.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===g.MAX_VALUE_16BITS||this.centralDirRecords===g.MAX_VALUE_16BITS||this.centralDirSize===g.MAX_VALUE_32BITS||this.centralDirOffset===g.MAX_VALUE_32BITS){if(this.zip64=!0,a=this.reader.lastIndexOfSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),-1===a)throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");this.reader.setIndex(a),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}},prepareReader:function(a){var b=g.getTypeOf(a);this.reader="string"!==b||j.uint8array?"nodebuffer"===b?new e(a):new f(g.transformTo("uint8array",a)):new d(a,this.loadOptions.optimizedBinaryString)},load:function(a){this.prepareReader(a),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},b.exports=c},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(a,b){"use strict";function c(a,b){this.options=a,this.loadOptions=b}var d=a("./stringReader"),e=a("./utils"),f=a("./compressedObject"),g=a("./object");c.prototype={isEncrypted:function(){return 1===(1&this.bitFlag)},useUTF8:function(){return 2048===(2048&this.bitFlag)},prepareCompressedContent:function(a,b,c){return function(){var d=a.index;a.setIndex(b);var e=a.readData(c);return a.setIndex(d),e}},prepareContent:function(a,b,c,d,f){return function(){var a=e.transformTo(d.uncompressInputType,this.getCompressedContent()),b=d.uncompress(a);if(b.length!==f)throw new Error("Bug : uncompressed data size mismatch");return b}},readLocalPart:function(a){var b,c;if(a.skip(22),this.fileNameLength=a.readInt(2),c=a.readInt(2),this.fileName=a.readString(this.fileNameLength),a.skip(c),-1==this.compressedSize||-1==this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory (compressedSize == -1 || uncompressedSize == -1)");if(b=e.findCompression(this.compressionMethod),null===b)throw new Error("Corrupted zip : compression "+e.pretty(this.compressionMethod)+" unknown (inner file : "+this.fileName+")");if(this.decompressed=new f,this.decompressed.compressedSize=this.compressedSize,this.decompressed.uncompressedSize=this.uncompressedSize,this.decompressed.crc32=this.crc32,this.decompressed.compressionMethod=this.compressionMethod,this.decompressed.getCompressedContent=this.prepareCompressedContent(a,a.index,this.compressedSize,b),this.decompressed.getContent=this.prepareContent(a,a.index,this.compressedSize,b,this.uncompressedSize),this.loadOptions.checkCRC32&&(this.decompressed=e.transformTo("string",this.decompressed.getContent()),g.crc32(this.decompressed)!==this.crc32))throw new Error("Corrupted zip : CRC32 mismatch")},readCentralPart:function(a){if(this.versionMadeBy=a.readString(2),this.versionNeeded=a.readInt(2),this.bitFlag=a.readInt(2),this.compressionMethod=a.readString(2),this.date=a.readDate(),this.crc32=a.readInt(4),this.compressedSize=a.readInt(4),this.uncompressedSize=a.readInt(4),this.fileNameLength=a.readInt(2),this.extraFieldsLength=a.readInt(2),this.fileCommentLength=a.readInt(2),this.diskNumberStart=a.readInt(2),this.internalFileAttributes=a.readInt(2),this.externalFileAttributes=a.readInt(4),this.localHeaderOffset=a.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");this.fileName=a.readString(this.fileNameLength),this.readExtraFields(a),this.parseZIP64ExtraField(a),this.fileComment=a.readString(this.fileCommentLength),this.dir=16&this.externalFileAttributes?!0:!1},parseZIP64ExtraField:function(){if(this.extraFields[1]){var a=new d(this.extraFields[1].value);this.uncompressedSize===e.MAX_VALUE_32BITS&&(this.uncompressedSize=a.readInt(8)),this.compressedSize===e.MAX_VALUE_32BITS&&(this.compressedSize=a.readInt(8)),this.localHeaderOffset===e.MAX_VALUE_32BITS&&(this.localHeaderOffset=a.readInt(8)),this.diskNumberStart===e.MAX_VALUE_32BITS&&(this.diskNumberStart=a.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index<e+this.extraFieldsLength;)b=a.readInt(2),c=a.readInt(2),d=a.readString(c),this.extraFields[b]={id:b,length:c,value:d}},handleUTF8:function(){if(this.useUTF8())this.fileName=g.utf8decode(this.fileName),this.fileComment=g.utf8decode(this.fileComment);else{var a=this.findExtraFieldUnicodePath();null!==a&&(this.fileName=a);var b=this.findExtraFieldUnicodeComment();null!==b&&(this.fileComment=b)}},findExtraFieldUnicodePath:function(){var a=this.extraFields[28789];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileName)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null},findExtraFieldUnicodeComment:function(){var a=this.extraFields[25461];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileComment)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null}},b.exports=c},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(a,b){"use strict";var c=a("./lib/utils/common").assign,d=a("./lib/deflate"),e=a("./lib/inflate"),f=a("./lib/zlib/constants"),g={};c(g,d,e,f),b.exports=g},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(a,b,c){"use strict";function d(a,b){var c=new s(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}function f(a,b){return b=b||{},b.gzip=!0,d(a,b)}var g=a("./zlib/deflate.js"),h=a("./utils/common"),i=a("./utils/strings"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=0,m=4,n=0,o=1,p=-1,q=0,r=8,s=function(a){this.options=h.assign({level:p,method:r,chunkSize:16384,windowBits:15,memLevel:8,strategy:q,to:""},a||{});var b=this.options;b.raw&&b.windowBits>0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+1])&a.hash_mask;a.insert&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+hb-1])&a.hash_mask,a.prev[f&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=f,f++,a.insert--,!(a.lookahead+a.insert<hb)););}while(a.lookahead<jb&&0!==a.strm.avail_in)}function n(a,b){var c=65535;for(c>a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),0!==c&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c)),a.match_length>=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart;while(0!==--a.match_length);a.strstart++}else a.strstart+=a.match_length,a.match_length=0,a.ins_h=a.window[a.strstart],a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+1])&a.hash_mask;else d=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++;if(d&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function p(a,b){for(var c,d,e;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),a.prev_length=a.match_length,a.prev_match=a.match_start,a.match_length=hb-1,0!==c&&a.prev_length<a.max_lazy_match&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c),a.match_length<=5&&(a.strategy===S||a.match_length===hb&&a.strstart-a.match_start>4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart);while(0!==--a.prev_length);if(a.match_available=0,a.match_length=hb-1,a.strstart++,d&&(h(a,!1),0===a.strm.avail_out))return sb}else if(a.match_available){if(d=D._tr_tally(a,0,a.window[a.strstart-1]),d&&h(a,!1),a.strstart++,a.lookahead--,0===a.strm.avail_out)return sb}else a.match_available=1,a.strstart++,a.lookahead--}return a.match_available&&(d=D._tr_tally(a,0,a.window[a.strstart-1]),a.match_available=0),a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function q(a,b){for(var c,d,e,f,g=a.window;;){if(a.lookahead<=ib){if(m(a),a.lookahead<=ib&&b===H)return sb;if(0===a.lookahead)break}if(a.match_length=0,a.lookahead>=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<<i.w_bits,i.w_mask=i.w_size-1,i.hash_bits=f+7,i.hash_size=1<<i.hash_bits,i.hash_mask=i.hash_size-1,i.hash_shift=~~((i.hash_bits+hb-1)/hb),i.window=new C.Buf8(2*i.w_size),i.head=new C.Buf16(i.hash_size),i.prev=new C.Buf16(i.w_size),i.lit_bufsize=1<<f+6,i.pending_buf_size=4*i.lit_bufsize,i.pending_buf=new C.Buf8(i.pending_buf_size),i.d_buf=i.lit_bufsize>>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.name.length?255&h.gzhead.name.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.comment.length?255&h.gzhead.comment.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<<e.lenbits)-1,u=(1<<e.distbits)-1;a:do{15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=r[p&t];b:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<<w)-1)];continue b}if(32&w){e.mode=d;break a}a.msg="invalid literal/length code",e.mode=c;break a}x=65535&v,w&=15,w&&(w>q&&(p+=B[f++]<<q,q+=8),x+=p&(1<<w)-1,p>>>=w,q-=w),15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=s[p&u];c:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<<w)-1)];continue c}a.msg="invalid distance code",e.mode=c;break a}if(y=65535&v,w&=15,w>q&&(p+=B[f++]<<q,q+=8,w>q&&(p+=B[f++]<<q,q+=8)),y+=p&(1<<w)-1,y>k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<<q)-1,a.next_in=f,a.next_out=h,a.avail_in=g>f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<<f.wbits,f.wnext=0,f.whave=0,f.window=new r.Buf8(f.wsize)),d>=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whave<f.wsize&&(f.whave+=e))),0}function m(a,b){var c,e,f,g,h,i,j,m,n,o,p,q,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Ab=0,Bb=new r.Buf8(4),Cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!a||!a.state||!a.output||!a.input&&0!==a.avail_in)return F;c=a.state,c.mode===V&&(c.mode=W),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,o=i,p=j,xb=C;a:for(;;)switch(c.mode){case K:if(0===c.wrap){c.mode=W;break}for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(2&c.wrap&&35615===m){c.check=0,Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<<wb,a.adler=c.check=1,c.mode=512&m?T:V,m=0,n=0;break;case L:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.flags=m,(255&c.flags)!==J){a.msg="unknown compression method",c.mode=lb;break}if(57344&c.flags){a.msg="unknown header flags set",c.mode=lb;break}c.head&&(c.head.text=m>>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.time=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.xflags=255&m,c.head.os=m>>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length=m,c.head&&(c.head.extra_len=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(65535&c.check)){a.msg="header crc mismatch",c.mode=lb;break}m=0,n=0}c.head&&(c.head.hcrc=c.flags>>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}a.adler=c.check=d(m),m=0,n=0,c.mode=U;case U:if(0===c.havedict)return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,E;a.adler=c.check=1,c.mode=V;case V:if(b===A||b===B)break a;case W:if(c.last){m>>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}switch(c.last=1&m,m>>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if((65535&m)!==(m>>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.nlen=(31&m)+257,m>>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.have<c.ncode;){for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.lens[Cb[c.have++]]=7&m,m>>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have<c.nlen+c.ndist;){for(;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(16>sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m>>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(rb&&0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.lencode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<<c.distbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.distcode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.offset+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<<n,n+=8}if(p-=j,a.total_out+=p,c.total+=p,p&&(a.adler=c.check=c.flags?t(c.check,f,p,h-p):s(c.check,f,p,h-p)),p=j,(c.flags?m:d(m))!==c.check){a.msg="incorrect data check",c.mode=lb;break}m=0,n=0}c.mode=jb;case jb:if(c.wrap&&c.flags){for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(4294967295&c.total)){a.msg="incorrect length check",c.mode=lb;break}m=0,n=0}c.mode=kb;case kb:xb=D;break a;case lb:xb=G;break a;case mb:return H;case nb:default:return F}return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,(c.wsize||p!==a.avail_out&&c.mode<lb&&(c.mode<ib||b!==z))&&l(a,a.output,a.next_out,p-a.avail_out)?(c.mode=mb,H):(o-=a.avail_in,p-=a.avail_out,a.total_in+=o,a.total_out+=p,c.total+=p,c.wrap&&p&&(a.adler=c.check=c.flags?t(c.check,f,p,a.next_out-p):s(c.check,f,p,a.next_out-p)),a.data_type=c.bits+(c.last?64:0)+(c.mode===V?128:0)+(c.mode===bb||c.mode===Y?256:0),(0===o&&0===p||b===z)&&xb===C&&(xb=I),xb)}function n(a){if(!a||!a.state)return F;var b=a.state;return b.window&&(b.window=null),a.state=null,C}function o(a,b){var c;return a&&a.state?(c=a.state,0===(2&c.wrap)?F:(c.head=b,b.done=!1,C)):F}var p,q,r=a("../utils/common"),s=a("./adler32"),t=a("./crc32"),u=a("./inffast"),v=a("./inftrees"),w=0,x=1,y=2,z=4,A=5,B=6,C=0,D=1,E=2,F=-2,G=-3,H=-4,I=-5,J=8,K=1,L=2,M=3,N=4,O=5,P=6,Q=7,R=8,S=9,T=10,U=11,V=12,W=13,X=14,Y=15,Z=16,$=17,_=18,ab=19,bb=20,cb=21,db=22,eb=23,fb=24,gb=25,hb=26,ib=27,jb=28,kb=29,lb=30,mb=31,nb=32,ob=852,pb=592,qb=15,rb=qb,sb=!0;c.inflateReset=g,c.inflateReset2=h,c.inflateResetKeep=f,c.inflateInit=j,c.inflateInit2=i,c.inflate=m,c.inflateEnd=n,c.inflateGetHeader=o,c.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(a,b){"use strict";var c=a("../utils/common"),d=15,e=852,f=592,g=0,h=1,i=2,j=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],k=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],l=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],m=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];b.exports=function(a,b,n,o,p,q,r,s){var t,u,v,w,x,y,z,A,B,C=s.bits,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=null,O=0,P=new c.Buf16(d+1),Q=new c.Buf16(d+1),R=null,S=0;for(D=0;d>=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<<H,w=L-1,a===h&&L>e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]<y?(A=0,B=r[E]):r[E]>y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<<D-J,u=1<<I,F=u;do u-=t,p[x+(M>>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<<D-1;M&t;)t>>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<<I;G>I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<<I,a===h&&L>e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<<a.bi_valid&65535,f(a,a.bi_buf),a.bi_buf=b>>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<<a.bi_valid&65535,a.bi_valid+=c)}function h(a,b,c){g(a,c[2*b],c[2*b+1])}function i(a,b){var c=0;do c|=1&a,a>>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<<ab[d];a++)gb[e++]=d;for(e>>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<<ab[d]-7;a++)gb[256+e++]=d;for(b=0;U>=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]<a[f]||a[e]===a[f]&&d[b]<=d[c]}function r(a,b,c){for(var d=a.heap[c],e=c<<1;e<=a.heap_len&&(e<a.heap_len&&q(b,a.heap[e+1],a.heap[e],a.depth)&&e++,!q(b,d,a.heap[e],a.depth));)a.heap[c]=a.heap[e],c=e,e<<=1;a.heap[c]=d}function s(a,b,c){var d,f,i,j,k=0;if(0!==a.last_lit)do d=a.pending_buf[a.d_buf+2*k]<<8|a.pending_buf[a.d_buf+2*k+1],f=a.pending_buf[a.l_buf+k],k++,0===d?h(a,f,b):(i=hb[f],h(a,i+P+1,b),j=_[i],0!==j&&(f-=ib[i],g(a,f,j)),d--,i=e(d),h(a,i,c),j=ab[i],0!==j&&(d-=jb[i],g(a,d,j)));while(k<a.last_lit);h(a,X,b)}function t(a,b){var c,d,e,f=b.dyn_tree,g=b.stat_desc.static_tree,h=b.stat_desc.has_stree,i=b.stat_desc.elems,j=-1;for(a.heap_len=0,a.heap_max=T,c=0;i>c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++h<i&&e===g||(j>h?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++j<k&&e===i)){if(l>j){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)});'use strict';tv.exportTo('tv.e.importer.ddms',function(){var Importer=tv.c.importer.Importer;var kPid=0;var kCategory='java';var kMethodLutEndMarker='\n*end\n';var kThreadsStart='\n*threads\n';var kMethodsStart='\n*methods\n';var kTraceMethodEnter=0x00;var kTraceMethodExit=0x01;var kTraceUnroll=0x02;var kTraceMethodActionMask=0x03;var kTraceHeaderLength=32;var kTraceMagicValue=0x574f4c53;var kTraceVersionSingleClock=2;var kTraceVersionDualClock=3;var kTraceRecordSizeSingleClock=10;var kTraceRecordSizeDualClock=14;function Reader(string_payload){this.position_=0;this.data_=JSZip.utils.transformTo('uint8array',string_payload);}
+var corrPeakTs=((minShift+corrPeakIdx)/this.sampleRate_);corrPeakTs*=1000;var syncStartTs=firstSyncEventTs-this.model_.bounds.min;var shiftTs=syncStartTs-corrPeakTs;return shiftTs;}};tr.importer.Importer.register(BattorImporter);return{BattorImporter:BattorImporter,_BattorImporterTestExports:TestExports};});!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";c.encode=function(a){for(var b,c,e,f,g,h,i,j="",k=0;k<a.length;)b=a.charCodeAt(k++),c=a.charCodeAt(k++),e=a.charCodeAt(k++),f=b>>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)f=d.indexOf(a.charAt(k++)),g=d.indexOf(a.charAt(k++)),h=d.indexOf(a.charAt(k++)),i=d.indexOf(a.charAt(k++)),b=f<<2|g>>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.length<a||0>a)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;g<e.length;g++)h=e[g],this.file(h.fileName,h.decompressed,{binary:!0,optimizedBinaryString:!0,date:h.date,dir:h.dir,comment:h.fileComment.length?h.fileComment:null,createFolders:b.createFolders});return f.zipComment.length&&(this.comment=f.zipComment),this}},{"./base64":1,"./zipEntries":22}],11:[function(a,b){(function(a){"use strict";b.exports=function(b,c){return new a(b,c)},b.exports.test=function(b){return a.isBuffer(b)}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],12:[function(a,b){"use strict";function c(a){this.data=a,this.length=this.data.length,this.index=0}var d=a("./uint8ArrayReader");c.prototype=new d,c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./uint8ArrayReader":18}],13:[function(a,b){"use strict";var c=a("./support"),d=a("./utils"),e=a("./crc32"),f=a("./signature"),g=a("./defaults"),h=a("./base64"),i=a("./compressions"),j=a("./compressedObject"),k=a("./nodeBuffer"),l=a("./utf8"),m=a("./stringWriter"),n=a("./uint8ArrayWriter"),o=function(a){if(a._data instanceof j&&(a._data=a._data.getContent(),a.options.binary=!0,a.options.base64=!1,"uint8array"===d.getTypeOf(a._data))){var b=a._data;a._data=new Uint8Array(b.length),0!==b.length&&a._data.set(b,0)}return a._data},p=function(a){var b=o(a),e=d.getTypeOf(b);return"string"===e?!a.options.binary&&c.nodebuffer?k(b,"utf-8"):a.asBinary():b},q=function(a){var b=o(this);return null===b||"undefined"==typeof b?"":(this.options.base64&&(b=h.decode(b)),b=a&&this.options.binary?A.utf8decode(b):d.transformTo("string",b),a||this.options.binary||(b=d.transformTo("string",A.utf8encode(b))),b)},r=function(a,b,c){this.name=a,this.dir=c.dir,this.date=c.date,this.comment=c.comment,this._data=b,this.options=c,this._initialMetadata={dir:c.dir,date:c.date}};r.prototype={asText:function(){return q.call(this,!0)},asBinary:function(){return q.call(this,!1)},asNodeBuffer:function(){var a=p(this);return d.transformTo("nodebuffer",a)},asUint8Array:function(){var a=p(this);return d.transformTo("uint8array",a)},asArrayBuffer:function(){return this.asUint8Array().buffer}};var s=function(a,b){var c,d="";for(c=0;b>c;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a<arguments.length;a++)for(b in arguments[a])arguments[a].hasOwnProperty(b)&&"undefined"==typeof c[b]&&(c[b]=arguments[a][b]);return c},u=function(a){return a=a||{},a.base64!==!0||null!==a.binary&&void 0!==a.binary||(a.binary=!0),a=t(a,g),a.date=a.date||new Date,null!==a.compression&&(a.compression=a.compression.toUpperCase()),a},v=function(a,b,c){var e,f=d.getTypeOf(b);if(c=u(c),c.createFolders&&(e=w(a))&&x.call(this,e,!0),c.dir||null===b||"undefined"==typeof b)c.base64=!1,c.binary=!1,b=null;else if("string"===f)c.binary&&!c.base64&&c.optimizedBinaryString!==!0&&(b=d.string2binary(b));else{if(c.base64=!1,c.binary=!0,!(f||b instanceof j))throw new Error("The data of '"+a+"' is in an unsupported format !");"arraybuffer"===f&&(b=d.transformTo("uint8array",b))}var g=new r(a,b,c);return this.files[a]=g,g},w=function(a){"/"==a.slice(-1)&&(a=a.substring(0,a.length-1));var b=a.lastIndexOf("/");return b>0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b?b:!1,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\x00",w+=p||q?"\x00\b":"\x00\x00",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\x00"+w+s(o.length,2)+"\x00\x00\x00\x00"+(j===!0?"\x00\x00\x00":"\x00\x00\x00\x00")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d<c.length;d++)delete this.files[c[d].name];return this},generate:function(a){a=t(a||{},{base64:!0,compression:"STORE",type:"base64",comment:null}),d.checkSupport(a.type);var b,c,e=[],g=0,j=0,k=d.transformTo("string",this.utf8encode(a.comment||this.comment||""));for(var l in this.files)if(this.files.hasOwnProperty(l)){var o=this.files[l],p=o.options.compression||a.compression.toUpperCase(),q=i[p];if(!q)throw new Error(p+" is not a valid compression method !");var r=y.call(this,o,q),u=z.call(this,l,o,r,g);g+=u.fileRecord.length+r.compressedSize,j+=u.dirRecord.length,e.push(u)}var v="";v=f.CENTRAL_DIRECTORY_END+"\x00\x00\x00\x00"+s(e.length,2)+s(e.length,2)+s(j,4)+s(g,4)+s(k.length,2)+k;var w=a.type.toLowerCase();for(b="uint8array"===w||"arraybuffer"===w||"blob"===w||"nodebuffer"===w?new n(g+j+v.length):new m(g+j+v.length),c=0;c<e.length;c++)b.append(e[c].fileRecord),b.append(e[c].compressedObject.compressedContent);for(c=0;c<e.length;c++)b.append(e[c].dirRecord);b.append(v);var x=b.finalize();switch(a.type.toLowerCase()){case"uint8array":case"arraybuffer":case"nodebuffer":return d.transformTo(a.type.toLowerCase(),x);case"blob":return d.arrayBuffer2Blob(d.transformTo("arraybuffer",x));case"base64":return a.base64?h.encode(x):x;default:return x}},crc32:function(a,b){return e(a,b)},utf8encode:function(a){return d.transformTo("string",l.utf8encode(a))},utf8decode:function(a){return l.utf8decode(a)}};b.exports=A},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(a,b,c){"use strict";c.LOCAL_FILE_HEADER="PK",c.CENTRAL_FILE_HEADER="PK",c.CENTRAL_DIRECTORY_END="PK",c.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",c.ZIP64_CENTRAL_DIRECTORY_END="PK",c.DATA_DESCRIPTOR="PK\b"},{}],15:[function(a,b){"use strict";function c(a,b){this.data=a,b||(this.data=e.string2binary(this.data)),this.length=this.data.length,this.index=0}var d=a("./dataReader"),e=a("./utils");c.prototype=new d,c.prototype.byteAt=function(a){return this.data.charCodeAt(a)},c.prototype.lastIndexOfSignature=function(a){return this.data.lastIndexOf(a)},c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5,"./utils":21}],16:[function(a,b){"use strict";var c=a("./utils"),d=function(){this.data=[]};d.prototype={append:function(a){a=c.transformTo("string",a),this.data.push(a)},finalize:function(){return this.data.join("")}},b.exports=d},{"./utils":21}],17:[function(a,b,c){(function(a){"use strict";if(c.base64=!0,c.array=!0,c.string=!0,c.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,c.nodebuffer="undefined"!=typeof a,c.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)c.blob=!1;else{var b=new ArrayBuffer(0);try{c.blob=0===new Blob([b],{type:"application/zip"}).size}catch(d){try{var e=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,f=new e;f.append(b),c.blob=0===f.getBlob("application/zip").size}catch(d){c.blob=!1}}}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],18:[function(a,b){"use strict";function c(a){a&&(this.data=a,this.length=this.data.length,this.index=0)}var d=a("./dataReader");c.prototype=new d,c.prototype.byteAt=function(a){return this.data[a]},c.prototype.lastIndexOfSignature=function(a){for(var b=a.charCodeAt(0),c=a.charCodeAt(1),d=a.charCodeAt(2),e=a.charCodeAt(3),f=this.length-4;f>=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;c<a.length;++c)b[c]=255&a.charCodeAt(c);return b}function f(a){var b=65536,d=[],e=a.length,f=c.getTypeOf(a),g=0,h=!0;try{switch(f){case"uint8array":String.fromCharCode.apply(null,new Uint8Array(0));break;case"nodebuffer":String.fromCharCode.apply(null,j(0))}}catch(i){h=!1}if(!h){for(var k="",l=0;l<a.length;l++)k+=String.fromCharCode(a[l]);return k}for(;e>g&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;c<a.length;c++)b[c]=a[c];return b}var h=a("./support"),i=a("./compressions"),j=a("./nodeBuffer");c.string2binary=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(255&a.charCodeAt(c));return b},c.arrayBuffer2Blob=function(a){c.checkSupport("blob");try{return new Blob([a],{type:"application/zip"})}catch(b){try{var d=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,e=new d;return e.append(a),e.getBlob("application/zip")}catch(b){throw new Error("Bug : can't construct the Blob.")}}},c.applyFromCharCode=f;var k={};k.string={string:d,array:function(a){return e(a,new Array(a.length))},arraybuffer:function(a){return k.string.uint8array(a).buffer},uint8array:function(a){return e(a,new Uint8Array(a.length))},nodebuffer:function(a){return e(a,j(a.length))}},k.array={string:f,array:d,arraybuffer:function(a){return new Uint8Array(a).buffer},uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(a)}},k.arraybuffer={string:function(a){return f(new Uint8Array(a))},array:function(a){return g(new Uint8Array(a),new Array(a.byteLength))},arraybuffer:d,uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(new Uint8Array(a))}},k.uint8array={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return a.buffer},uint8array:d,nodebuffer:function(a){return j(a)}},k.nodebuffer={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return k.nodebuffer.uint8array(a).buffer},uint8array:function(a){return g(a,new Uint8Array(a.length))},nodebuffer:d},c.transformTo=function(a,b){if(b||(b=""),!a)return b;c.checkSupport(a);var d=c.getTypeOf(b),e=k[d][a](b);return e},c.getTypeOf=function(a){return"string"==typeof a?"string":"[object Array]"===Object.prototype.toString.call(a)?"array":h.nodebuffer&&j.test(a)?"nodebuffer":h.uint8array&&a instanceof Uint8Array?"uint8array":h.arraybuffer&&a instanceof ArrayBuffer?"arraybuffer":void 0},c.checkSupport=function(a){var b=h[a.toLowerCase()];if(!b)throw new Error(a+" is not supported by this browser")},c.MAX_VALUE_16BITS=65535,c.MAX_VALUE_32BITS=-1,c.pretty=function(a){var b,c,d="";for(c=0;c<(a||"").length;c++)b=a.charCodeAt(c),d+="\\x"+(16>b?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a<this.files.length;a++)b=this.files[a],this.reader.setIndex(b.localHeaderOffset),this.checkSignature(h.LOCAL_FILE_HEADER),b.readLocalPart(this.reader),b.handleUTF8()},readCentralDir:function(){var a;for(this.reader.setIndex(this.centralDirOffset);this.reader.readString(4)===h.CENTRAL_FILE_HEADER;)a=new i({zip64:this.zip64},this.loadOptions),a.readCentralPart(this.reader),this.files.push(a)},readEndOfCentral:function(){var a=this.reader.lastIndexOfSignature(h.CENTRAL_DIRECTORY_END);if(-1===a)throw new Error("Corrupted zip : can't find end of central directory");if(this.reader.setIndex(a),this.checkSignature(h.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===g.MAX_VALUE_16BITS||this.diskWithCentralDirStart===g.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===g.MAX_VALUE_16BITS||this.centralDirRecords===g.MAX_VALUE_16BITS||this.centralDirSize===g.MAX_VALUE_32BITS||this.centralDirOffset===g.MAX_VALUE_32BITS){if(this.zip64=!0,a=this.reader.lastIndexOfSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),-1===a)throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");this.reader.setIndex(a),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}},prepareReader:function(a){var b=g.getTypeOf(a);this.reader="string"!==b||j.uint8array?"nodebuffer"===b?new e(a):new f(g.transformTo("uint8array",a)):new d(a,this.loadOptions.optimizedBinaryString)},load:function(a){this.prepareReader(a),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},b.exports=c},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(a,b){"use strict";function c(a,b){this.options=a,this.loadOptions=b}var d=a("./stringReader"),e=a("./utils"),f=a("./compressedObject"),g=a("./object");c.prototype={isEncrypted:function(){return 1===(1&this.bitFlag)},useUTF8:function(){return 2048===(2048&this.bitFlag)},prepareCompressedContent:function(a,b,c){return function(){var d=a.index;a.setIndex(b);var e=a.readData(c);return a.setIndex(d),e}},prepareContent:function(a,b,c,d,f){return function(){var a=e.transformTo(d.uncompressInputType,this.getCompressedContent()),b=d.uncompress(a);if(b.length!==f)throw new Error("Bug : uncompressed data size mismatch");return b}},readLocalPart:function(a){var b,c;if(a.skip(22),this.fileNameLength=a.readInt(2),c=a.readInt(2),this.fileName=a.readString(this.fileNameLength),a.skip(c),-1==this.compressedSize||-1==this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory (compressedSize == -1 || uncompressedSize == -1)");if(b=e.findCompression(this.compressionMethod),null===b)throw new Error("Corrupted zip : compression "+e.pretty(this.compressionMethod)+" unknown (inner file : "+this.fileName+")");if(this.decompressed=new f,this.decompressed.compressedSize=this.compressedSize,this.decompressed.uncompressedSize=this.uncompressedSize,this.decompressed.crc32=this.crc32,this.decompressed.compressionMethod=this.compressionMethod,this.decompressed.getCompressedContent=this.prepareCompressedContent(a,a.index,this.compressedSize,b),this.decompressed.getContent=this.prepareContent(a,a.index,this.compressedSize,b,this.uncompressedSize),this.loadOptions.checkCRC32&&(this.decompressed=e.transformTo("string",this.decompressed.getContent()),g.crc32(this.decompressed)!==this.crc32))throw new Error("Corrupted zip : CRC32 mismatch")},readCentralPart:function(a){if(this.versionMadeBy=a.readString(2),this.versionNeeded=a.readInt(2),this.bitFlag=a.readInt(2),this.compressionMethod=a.readString(2),this.date=a.readDate(),this.crc32=a.readInt(4),this.compressedSize=a.readInt(4),this.uncompressedSize=a.readInt(4),this.fileNameLength=a.readInt(2),this.extraFieldsLength=a.readInt(2),this.fileCommentLength=a.readInt(2),this.diskNumberStart=a.readInt(2),this.internalFileAttributes=a.readInt(2),this.externalFileAttributes=a.readInt(4),this.localHeaderOffset=a.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");this.fileName=a.readString(this.fileNameLength),this.readExtraFields(a),this.parseZIP64ExtraField(a),this.fileComment=a.readString(this.fileCommentLength),this.dir=16&this.externalFileAttributes?!0:!1},parseZIP64ExtraField:function(){if(this.extraFields[1]){var a=new d(this.extraFields[1].value);this.uncompressedSize===e.MAX_VALUE_32BITS&&(this.uncompressedSize=a.readInt(8)),this.compressedSize===e.MAX_VALUE_32BITS&&(this.compressedSize=a.readInt(8)),this.localHeaderOffset===e.MAX_VALUE_32BITS&&(this.localHeaderOffset=a.readInt(8)),this.diskNumberStart===e.MAX_VALUE_32BITS&&(this.diskNumberStart=a.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index<e+this.extraFieldsLength;)b=a.readInt(2),c=a.readInt(2),d=a.readString(c),this.extraFields[b]={id:b,length:c,value:d}},handleUTF8:function(){if(this.useUTF8())this.fileName=g.utf8decode(this.fileName),this.fileComment=g.utf8decode(this.fileComment);else{var a=this.findExtraFieldUnicodePath();null!==a&&(this.fileName=a);var b=this.findExtraFieldUnicodeComment();null!==b&&(this.fileComment=b)}},findExtraFieldUnicodePath:function(){var a=this.extraFields[28789];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileName)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null},findExtraFieldUnicodeComment:function(){var a=this.extraFields[25461];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileComment)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null}},b.exports=c},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(a,b){"use strict";var c=a("./lib/utils/common").assign,d=a("./lib/deflate"),e=a("./lib/inflate"),f=a("./lib/zlib/constants"),g={};c(g,d,e,f),b.exports=g},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(a,b,c){"use strict";function d(a,b){var c=new s(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}function f(a,b){return b=b||{},b.gzip=!0,d(a,b)}var g=a("./zlib/deflate.js"),h=a("./utils/common"),i=a("./utils/strings"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=0,m=4,n=0,o=1,p=-1,q=0,r=8,s=function(a){this.options=h.assign({level:p,method:r,chunkSize:16384,windowBits:15,memLevel:8,strategy:q,to:""},a||{});var b=this.options;b.raw&&b.windowBits>0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+1])&a.hash_mask;a.insert&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+hb-1])&a.hash_mask,a.prev[f&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=f,f++,a.insert--,!(a.lookahead+a.insert<hb)););}while(a.lookahead<jb&&0!==a.strm.avail_in)}function n(a,b){var c=65535;for(c>a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),0!==c&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c)),a.match_length>=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart;while(0!==--a.match_length);a.strstart++}else a.strstart+=a.match_length,a.match_length=0,a.ins_h=a.window[a.strstart],a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+1])&a.hash_mask;else d=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++;if(d&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function p(a,b){for(var c,d,e;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),a.prev_length=a.match_length,a.prev_match=a.match_start,a.match_length=hb-1,0!==c&&a.prev_length<a.max_lazy_match&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c),a.match_length<=5&&(a.strategy===S||a.match_length===hb&&a.strstart-a.match_start>4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart);while(0!==--a.prev_length);if(a.match_available=0,a.match_length=hb-1,a.strstart++,d&&(h(a,!1),0===a.strm.avail_out))return sb}else if(a.match_available){if(d=D._tr_tally(a,0,a.window[a.strstart-1]),d&&h(a,!1),a.strstart++,a.lookahead--,0===a.strm.avail_out)return sb}else a.match_available=1,a.strstart++,a.lookahead--}return a.match_available&&(d=D._tr_tally(a,0,a.window[a.strstart-1]),a.match_available=0),a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function q(a,b){for(var c,d,e,f,g=a.window;;){if(a.lookahead<=ib){if(m(a),a.lookahead<=ib&&b===H)return sb;if(0===a.lookahead)break}if(a.match_length=0,a.lookahead>=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<<i.w_bits,i.w_mask=i.w_size-1,i.hash_bits=f+7,i.hash_size=1<<i.hash_bits,i.hash_mask=i.hash_size-1,i.hash_shift=~~((i.hash_bits+hb-1)/hb),i.window=new C.Buf8(2*i.w_size),i.head=new C.Buf16(i.hash_size),i.prev=new C.Buf16(i.w_size),i.lit_bufsize=1<<f+6,i.pending_buf_size=4*i.lit_bufsize,i.pending_buf=new C.Buf8(i.pending_buf_size),i.d_buf=i.lit_bufsize>>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.name.length?255&h.gzhead.name.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.comment.length?255&h.gzhead.comment.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<<e.lenbits)-1,u=(1<<e.distbits)-1;a:do{15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=r[p&t];b:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<<w)-1)];continue b}if(32&w){e.mode=d;break a}a.msg="invalid literal/length code",e.mode=c;break a}x=65535&v,w&=15,w&&(w>q&&(p+=B[f++]<<q,q+=8),x+=p&(1<<w)-1,p>>>=w,q-=w),15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=s[p&u];c:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<<w)-1)];continue c}a.msg="invalid distance code",e.mode=c;break a}if(y=65535&v,w&=15,w>q&&(p+=B[f++]<<q,q+=8,w>q&&(p+=B[f++]<<q,q+=8)),y+=p&(1<<w)-1,y>k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<<q)-1,a.next_in=f,a.next_out=h,a.avail_in=g>f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<<f.wbits,f.wnext=0,f.whave=0,f.window=new r.Buf8(f.wsize)),d>=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whave<f.wsize&&(f.whave+=e))),0}function m(a,b){var c,e,f,g,h,i,j,m,n,o,p,q,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Ab=0,Bb=new r.Buf8(4),Cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!a||!a.state||!a.output||!a.input&&0!==a.avail_in)return F;c=a.state,c.mode===V&&(c.mode=W),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,o=i,p=j,xb=C;a:for(;;)switch(c.mode){case K:if(0===c.wrap){c.mode=W;break}for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(2&c.wrap&&35615===m){c.check=0,Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<<wb,a.adler=c.check=1,c.mode=512&m?T:V,m=0,n=0;break;case L:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.flags=m,(255&c.flags)!==J){a.msg="unknown compression method",c.mode=lb;break}if(57344&c.flags){a.msg="unknown header flags set",c.mode=lb;break}c.head&&(c.head.text=m>>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.time=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.xflags=255&m,c.head.os=m>>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length=m,c.head&&(c.head.extra_len=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(65535&c.check)){a.msg="header crc mismatch",c.mode=lb;break}m=0,n=0}c.head&&(c.head.hcrc=c.flags>>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}a.adler=c.check=d(m),m=0,n=0,c.mode=U;case U:if(0===c.havedict)return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,E;a.adler=c.check=1,c.mode=V;case V:if(b===A||b===B)break a;case W:if(c.last){m>>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}switch(c.last=1&m,m>>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if((65535&m)!==(m>>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.nlen=(31&m)+257,m>>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.have<c.ncode;){for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.lens[Cb[c.have++]]=7&m,m>>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have<c.nlen+c.ndist;){for(;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(16>sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m>>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(rb&&0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.lencode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<<c.distbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.distcode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.offset+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<<n,n+=8}if(p-=j,a.total_out+=p,c.total+=p,p&&(a.adler=c.check=c.flags?t(c.check,f,p,h-p):s(c.check,f,p,h-p)),p=j,(c.flags?m:d(m))!==c.check){a.msg="incorrect data check",c.mode=lb;break}m=0,n=0}c.mode=jb;case jb:if(c.wrap&&c.flags){for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(4294967295&c.total)){a.msg="incorrect length check",c.mode=lb;break}m=0,n=0}c.mode=kb;case kb:xb=D;break a;case lb:xb=G;break a;case mb:return H;case nb:default:return F}return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,(c.wsize||p!==a.avail_out&&c.mode<lb&&(c.mode<ib||b!==z))&&l(a,a.output,a.next_out,p-a.avail_out)?(c.mode=mb,H):(o-=a.avail_in,p-=a.avail_out,a.total_in+=o,a.total_out+=p,c.total+=p,c.wrap&&p&&(a.adler=c.check=c.flags?t(c.check,f,p,a.next_out-p):s(c.check,f,p,a.next_out-p)),a.data_type=c.bits+(c.last?64:0)+(c.mode===V?128:0)+(c.mode===bb||c.mode===Y?256:0),(0===o&&0===p||b===z)&&xb===C&&(xb=I),xb)}function n(a){if(!a||!a.state)return F;var b=a.state;return b.window&&(b.window=null),a.state=null,C}function o(a,b){var c;return a&&a.state?(c=a.state,0===(2&c.wrap)?F:(c.head=b,b.done=!1,C)):F}var p,q,r=a("../utils/common"),s=a("./adler32"),t=a("./crc32"),u=a("./inffast"),v=a("./inftrees"),w=0,x=1,y=2,z=4,A=5,B=6,C=0,D=1,E=2,F=-2,G=-3,H=-4,I=-5,J=8,K=1,L=2,M=3,N=4,O=5,P=6,Q=7,R=8,S=9,T=10,U=11,V=12,W=13,X=14,Y=15,Z=16,$=17,_=18,ab=19,bb=20,cb=21,db=22,eb=23,fb=24,gb=25,hb=26,ib=27,jb=28,kb=29,lb=30,mb=31,nb=32,ob=852,pb=592,qb=15,rb=qb,sb=!0;c.inflateReset=g,c.inflateReset2=h,c.inflateResetKeep=f,c.inflateInit=j,c.inflateInit2=i,c.inflate=m,c.inflateEnd=n,c.inflateGetHeader=o,c.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(a,b){"use strict";var c=a("../utils/common"),d=15,e=852,f=592,g=0,h=1,i=2,j=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],k=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],l=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],m=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];b.exports=function(a,b,n,o,p,q,r,s){var t,u,v,w,x,y,z,A,B,C=s.bits,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=null,O=0,P=new c.Buf16(d+1),Q=new c.Buf16(d+1),R=null,S=0;for(D=0;d>=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<<H,w=L-1,a===h&&L>e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]<y?(A=0,B=r[E]):r[E]>y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<<D-J,u=1<<I,F=u;do u-=t,p[x+(M>>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<<D-1;M&t;)t>>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<<I;G>I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<<I,a===h&&L>e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<<a.bi_valid&65535,f(a,a.bi_buf),a.bi_buf=b>>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<<a.bi_valid&65535,a.bi_valid+=c)}function h(a,b,c){g(a,c[2*b],c[2*b+1])}function i(a,b){var c=0;do c|=1&a,a>>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<<ab[d];a++)gb[e++]=d;for(e>>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<<ab[d]-7;a++)gb[256+e++]=d;for(b=0;U>=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]<a[f]||a[e]===a[f]&&d[b]<=d[c]}function r(a,b,c){for(var d=a.heap[c],e=c<<1;e<=a.heap_len&&(e<a.heap_len&&q(b,a.heap[e+1],a.heap[e],a.depth)&&e++,!q(b,d,a.heap[e],a.depth));)a.heap[c]=a.heap[e],c=e,e<<=1;a.heap[c]=d}function s(a,b,c){var d,f,i,j,k=0;if(0!==a.last_lit)do d=a.pending_buf[a.d_buf+2*k]<<8|a.pending_buf[a.d_buf+2*k+1],f=a.pending_buf[a.l_buf+k],k++,0===d?h(a,f,b):(i=hb[f],h(a,i+P+1,b),j=_[i],0!==j&&(f-=ib[i],g(a,f,j)),d--,i=e(d),h(a,i,c),j=ab[i],0!==j&&(d-=jb[i],g(a,d,j)));while(k<a.last_lit);h(a,X,b)}function t(a,b){var c,d,e,f=b.dyn_tree,g=b.stat_desc.static_tree,h=b.stat_desc.has_stree,i=b.stat_desc.elems,j=-1;for(a.heap_len=0,a.heap_max=T,c=0;i>c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++h<i&&e===g||(j>h?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++j<k&&e===i)){if(l>j){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)});'use strict';tr.exportTo('tr.e.importer.ddms',function(){var Importer=tr.importer.Importer;var kPid=0;var kCategory='java';var kMethodLutEndMarker='\n*end\n';var kThreadsStart='\n*threads\n';var kMethodsStart='\n*methods\n';var kTraceMethodEnter=0x00;var kTraceMethodExit=0x01;var kTraceUnroll=0x02;var kTraceMethodActionMask=0x03;var kTraceHeaderLength=32;var kTraceMagicValue=0x574f4c53;var kTraceVersionSingleClock=2;var kTraceVersionDualClock=3;var kTraceRecordSizeSingleClock=10;var kTraceRecordSizeDualClock=14;function Reader(string_payload){this.position_=0;this.data_=JSZip.utils.transformTo('uint8array',string_payload);}
 Reader.prototype={__proto__:Object.prototype,uint8:function(){var result=this.data_[this.position_];this.position_+=1;return result;},uint16:function(){var result=0;result+=this.uint8();result+=this.uint8()<<8;return result;},uint32:function(){var result=0;result+=this.uint8();result+=this.uint8()<<8;result+=this.uint8()<<16;result+=this.uint8()<<24;return result;},uint64:function(){var low=this.uint32();var high=this.uint32();var low_str=('0000000'+low.toString(16)).substr(-8);var high_str=('0000000'+high.toString(16)).substr(-8);var result=high_str+low_str;return result;},seekTo:function(position){this.position_=position;},hasMore:function(){return this.position_<this.data_.length;}};function DdmsImporter(model,data){this.importPriority=3;this.model_=model;this.data_=data;}
 DdmsImporter.canImport=function(data){if(typeof(data)==='string'||data instanceof String){var header=data.slice(0,1000);return header.startsWith('*version\n')&&header.indexOf('\nvm=')>=0&&header.indexOf(kThreadsStart)>=0;}
 return false;};DdmsImporter.prototype={__proto__:Importer.prototype,get model(){return this.model_;},importEvents:function(isSecondaryImport){var divider=this.data_.indexOf(kMethodLutEndMarker)+
@@ -3704,18 +3778,18 @@
 this.version_=traceReader.uint16();if(this.version_!=kTraceVersionDualClock){throw Error('Unknown version');}
 var dataOffest=traceReader.uint16();var startDateTime=traceReader.uint64();var recordSize=traceReader.uint16();traceReader.seekTo(dataOffest);while(traceReader.hasMore()){this.parseTraceEntry(traceReader);}},parseTraceEntry:function(reader){var tid=reader.uint16();var methodPacked=reader.uint32();var cpuSinceStart=reader.uint32();var wallClockSinceStart=reader.uint32();var method=methodPacked&~kTraceMethodActionMask;var action=methodPacked&kTraceMethodActionMask;var thread=this.getTid(tid);method=this.getMethodName(method);if(action==kTraceMethodEnter){thread.sliceGroup.beginSlice(kCategory,method,wallClockSinceStart,undefined,cpuSinceStart);}else if(thread.sliceGroup.openSliceCount){thread.sliceGroup.endSlice(wallClockSinceStart,cpuSinceStart);}},parseThreads:function(){var threads=this.metadata_.slice(this.metadata_.indexOf(kThreadsStart)+
 kThreadsStart.length);threads=threads.slice(0,threads.indexOf('\n*'));threads=threads.split('\n');threads.forEach(this.parseThread.bind(this));},parseThread:function(thread_line){var tid=thread_line.slice(0,thread_line.indexOf('\t'));var thread=this.getTid(parseInt(tid));thread.name=thread_line.slice(thread_line.indexOf('\t')+1);},getTid:function(tid){return this.model_.getOrCreateProcess(kPid).getOrCreateThread(tid);},parseMethods:function(){var methods=this.metadata_.slice(this.metadata_.indexOf(kMethodsStart)+
-kMethodsStart.length);methods=methods.slice(0,methods.indexOf('\n*'));methods=methods.split('\n');methods.forEach(this.parseMethod.bind(this));},parseMethod:function(method_line){var data=method_line.split('\t');var methodId=parseInt(data[0]);var methodName=data[1]+'.'+data[2]+data[3];this.addMethod(methodId,methodName);},addMethod:function(methodId,methodName){this.methods_[methodId]=methodName;},getMethodName:function(methodId){return this.methods_[methodId];}};tv.c.importer.Importer.register(DdmsImporter);return{DdmsImporter:DdmsImporter};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){function Parser(importer){this.importer=importer;this.model=importer.model;}
-Parser.prototype={__proto__:Object.prototype};var options=new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);options.mandatoryBaseClass=Parser;tv.b.decorateExtensionRegistry(Parser,options);return{Parser:Parser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function BusParser(importer){Parser.call(this,importer);importer.registerEventHandler('memory_bus_usage',BusParser.prototype.traceMarkWriteBusEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
-BusParser.prototype={__proto__:Parser.prototype,traceMarkWriteBusEvent:function(eventName,cpuNumber,pid,ts,eventBase,threadName){var re=new RegExp('bus=(\\S+) rw_bytes=(\\d+) r_bytes=(\\d+) '+'w_bytes=(\\d+) cycles=(\\d+) ns=(\\d+)');var event=re.exec(eventBase.details);var name=event[1];var rw_bytes=parseInt(event[2]);var r_bytes=parseInt(event[3]);var w_bytes=parseInt(event[4]);var cycles=parseInt(event[5]);var ns=parseInt(event[6]);var r_bw=r_bytes*1000000000/ns;r_bw/=1024*1024;var w_bw=w_bytes*1000000000/ns;w_bw/=1024*1024;var ctr=this.model_.kernel.getOrCreateCounter(null,'bus '+name+' read');if(ctr.numSeries===0){ctr.addSeries(new tv.c.trace_model.CounterSeries('value',tv.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
-ctr.series.forEach(function(series){series.addCounterSample(ts,r_bw);});ctr=this.model_.kernel.getOrCreateCounter(null,'bus '+name+' write');if(ctr.numSeries===0){ctr.addSeries(new tv.c.trace_model.CounterSeries('value',tv.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
-ctr.series.forEach(function(series){series.addCounterSample(ts,r_bw);});return true;}};Parser.register(BusParser);return{BusParser:BusParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function ClockParser(importer){Parser.call(this,importer);importer.registerEventHandler('clock_set_rate',ClockParser.prototype.traceMarkWriteClockEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
-ClockParser.prototype={__proto__:Parser.prototype,traceMarkWriteClockEvent:function(eventName,cpuNumber,pid,ts,eventBase,threadName){var event=/(\S+) state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);var name=event[1];var rate=parseInt(event[2]);var ctr=this.model_.kernel.getOrCreateCounter(null,name);if(ctr.numSeries===0){ctr.addSeries(new tv.c.trace_model.CounterSeries('value',tv.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
-ctr.series.forEach(function(series){series.addCounterSample(ts,rate);});return true;}};Parser.register(ClockParser);return{ClockParser:ClockParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function CpufreqParser(importer){Parser.call(this,importer);importer.registerEventHandler('cpufreq_interactive_up',CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_down',CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_already',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_notyet',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_setspeed',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_target',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_boost',CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_unboost',CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));}
+kMethodsStart.length);methods=methods.slice(0,methods.indexOf('\n*'));methods=methods.split('\n');methods.forEach(this.parseMethod.bind(this));},parseMethod:function(method_line){var data=method_line.split('\t');var methodId=parseInt(data[0]);var methodName=data[1]+'.'+data[2]+data[3];this.addMethod(methodId,methodName);},addMethod:function(methodId,methodName){this.methods_[methodId]=methodName;},getMethodName:function(methodId){return this.methods_[methodId];}};tr.importer.Importer.register(DdmsImporter);return{DdmsImporter:DdmsImporter};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){function Parser(importer){this.importer=importer;this.model=importer.model;}
+Parser.prototype={__proto__:Object.prototype};var options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.mandatoryBaseClass=Parser;tr.b.decorateExtensionRegistry(Parser,options);return{Parser:Parser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function BusParser(importer){Parser.call(this,importer);importer.registerEventHandler('memory_bus_usage',BusParser.prototype.traceMarkWriteBusEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+BusParser.prototype={__proto__:Parser.prototype,traceMarkWriteBusEvent:function(eventName,cpuNumber,pid,ts,eventBase,threadName){var re=new RegExp('bus=(\\S+) rw_bytes=(\\d+) r_bytes=(\\d+) '+'w_bytes=(\\d+) cycles=(\\d+) ns=(\\d+)');var event=re.exec(eventBase.details);var name=event[1];var rw_bytes=parseInt(event[2]);var r_bytes=parseInt(event[3]);var w_bytes=parseInt(event[4]);var cycles=parseInt(event[5]);var ns=parseInt(event[6]);var r_bw=r_bytes*1000000000/ns;r_bw/=1024*1024;var w_bw=w_bytes*1000000000/ns;w_bw/=1024*1024;var ctr=this.model_.kernel.getOrCreateCounter(null,'bus '+name+' read');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',tr.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,r_bw);});ctr=this.model_.kernel.getOrCreateCounter(null,'bus '+name+' write');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',tr.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,r_bw);});return true;}};Parser.register(BusParser);return{BusParser:BusParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function ClockParser(importer){Parser.call(this,importer);importer.registerEventHandler('clock_set_rate',ClockParser.prototype.traceMarkWriteClockEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+ClockParser.prototype={__proto__:Parser.prototype,traceMarkWriteClockEvent:function(eventName,cpuNumber,pid,ts,eventBase,threadName){var event=/(\S+) state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);var name=event[1];var rate=parseInt(event[2]);var ctr=this.model_.kernel.getOrCreateCounter(null,name);if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',tr.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,rate);});return true;}};Parser.register(ClockParser);return{ClockParser:ClockParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function CpufreqParser(importer){Parser.call(this,importer);importer.registerEventHandler('cpufreq_interactive_up',CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_down',CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_already',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_notyet',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_setspeed',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_target',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_boost',CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_unboost',CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));}
 function splitData(input){var data={};var args=input.split(/\s+/);var len=args.length;for(var i=0;i<len;i++){var item=args[i].split('=');data[item[0]]=parseInt(item[1]);}
 return data;}
-CpufreqParser.prototype={__proto__:Parser.prototype,cpufreqSlice:function(ts,eventName,cpu,args){var kthread=this.importer.getOrCreatePseudoThread('cpufreq');kthread.openSlice=eventName;var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},cpufreqBoostSlice:function(ts,eventName,args){var kthread=this.importer.getOrCreatePseudoThread('cpufreq_boost');kthread.openSlice=eventName;var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},cpufreqUpDownEvent:function(eventName,cpuNumber,pid,ts,eventBase){var data=splitData(eventBase.details);this.cpufreqSlice(ts,eventName,data.cpu,data);return true;},cpufreqTargetEvent:function(eventName,cpuNumber,pid,ts,eventBase){var data=splitData(eventBase.details);this.cpufreqSlice(ts,eventName,data.cpu,data);return true;},cpufreqBoostUnboostEvent:function(eventName,cpuNumber,pid,ts,eventBase){this.cpufreqBoostSlice(ts,eventName,{type:eventBase.details});return true;}};Parser.register(CpufreqParser);return{CpufreqParser:CpufreqParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function DiskParser(importer){Parser.call(this,importer);importer.registerEventHandler('f2fs_write_begin',DiskParser.prototype.f2fsWriteBeginEvent.bind(this));importer.registerEventHandler('f2fs_write_end',DiskParser.prototype.f2fsWriteEndEvent.bind(this));importer.registerEventHandler('f2fs_sync_file_enter',DiskParser.prototype.f2fsSyncFileEnterEvent.bind(this));importer.registerEventHandler('f2fs_sync_file_exit',DiskParser.prototype.f2fsSyncFileExitEvent.bind(this));importer.registerEventHandler('ext4_sync_file_enter',DiskParser.prototype.ext4SyncFileEnterEvent.bind(this));importer.registerEventHandler('ext4_sync_file_exit',DiskParser.prototype.ext4SyncFileExitEvent.bind(this));importer.registerEventHandler('ext4_da_write_begin',DiskParser.prototype.ext4WriteBeginEvent.bind(this));importer.registerEventHandler('ext4_da_write_end',DiskParser.prototype.ext4WriteEndEvent.bind(this));importer.registerEventHandler('block_rq_issue',DiskParser.prototype.blockRqIssueEvent.bind(this));importer.registerEventHandler('block_rq_complete',DiskParser.prototype.blockRqCompleteEvent.bind(this));}
-DiskParser.prototype={__proto__:Parser.prototype,openAsyncSlice:function(ts,category,threadName,pid,key,name){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);var asyncSliceConstructor=tv.c.trace_model.AsyncSlice.getConstructor(category,name);var slice=new asyncSliceConstructor(category,name,tv.b.ui.getColorIdForGeneralPurposeString(name),ts);slice.startThread=kthread.thread;if(!kthread.openAsyncSlices){kthread.openAsyncSlices={};}
-kthread.openAsyncSlices[key]=slice;},closeAsyncSlice:function(ts,category,threadName,pid,key,args){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);if(kthread.openAsyncSlices){var slice=kthread.openAsyncSlices[key];if(slice){slice.duration=ts-slice.start;slice.args=args;slice.endThread=kthread.thread;slice.subSlices=[new tv.c.trace_model.AsyncSlice(category,slice.title,slice.colorId,slice.start,slice.args,slice.duration)];kthread.thread.asyncSliceGroup.push(slice);delete kthread.openAsyncSlices[key];}}},f2fsWriteBeginEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/dev = \((\d+,\d+)\), ino = (\d+), pos = (\d+), len = (\d+), flags = (\d+)/.exec(eventBase.details);if(!event)
+CpufreqParser.prototype={__proto__:Parser.prototype,cpufreqSlice:function(ts,eventName,cpu,args){var kthread=this.importer.getOrCreatePseudoThread('cpufreq');kthread.openSlice=eventName;var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},cpufreqBoostSlice:function(ts,eventName,args){var kthread=this.importer.getOrCreatePseudoThread('cpufreq_boost');kthread.openSlice=eventName;var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},cpufreqUpDownEvent:function(eventName,cpuNumber,pid,ts,eventBase){var data=splitData(eventBase.details);this.cpufreqSlice(ts,eventName,data.cpu,data);return true;},cpufreqTargetEvent:function(eventName,cpuNumber,pid,ts,eventBase){var data=splitData(eventBase.details);this.cpufreqSlice(ts,eventName,data.cpu,data);return true;},cpufreqBoostUnboostEvent:function(eventName,cpuNumber,pid,ts,eventBase){this.cpufreqBoostSlice(ts,eventName,{type:eventBase.details});return true;}};Parser.register(CpufreqParser);return{CpufreqParser:CpufreqParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function DiskParser(importer){Parser.call(this,importer);importer.registerEventHandler('f2fs_write_begin',DiskParser.prototype.f2fsWriteBeginEvent.bind(this));importer.registerEventHandler('f2fs_write_end',DiskParser.prototype.f2fsWriteEndEvent.bind(this));importer.registerEventHandler('f2fs_sync_file_enter',DiskParser.prototype.f2fsSyncFileEnterEvent.bind(this));importer.registerEventHandler('f2fs_sync_file_exit',DiskParser.prototype.f2fsSyncFileExitEvent.bind(this));importer.registerEventHandler('ext4_sync_file_enter',DiskParser.prototype.ext4SyncFileEnterEvent.bind(this));importer.registerEventHandler('ext4_sync_file_exit',DiskParser.prototype.ext4SyncFileExitEvent.bind(this));importer.registerEventHandler('ext4_da_write_begin',DiskParser.prototype.ext4WriteBeginEvent.bind(this));importer.registerEventHandler('ext4_da_write_end',DiskParser.prototype.ext4WriteEndEvent.bind(this));importer.registerEventHandler('block_rq_issue',DiskParser.prototype.blockRqIssueEvent.bind(this));importer.registerEventHandler('block_rq_complete',DiskParser.prototype.blockRqCompleteEvent.bind(this));}
+DiskParser.prototype={__proto__:Parser.prototype,openAsyncSlice:function(ts,category,threadName,pid,key,name){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);var asyncSliceConstructor=tr.model.AsyncSlice.getConstructor(category,name);var slice=new asyncSliceConstructor(category,name,tr.b.ui.getColorIdForGeneralPurposeString(name),ts);slice.startThread=kthread.thread;if(!kthread.openAsyncSlices){kthread.openAsyncSlices={};}
+kthread.openAsyncSlices[key]=slice;},closeAsyncSlice:function(ts,category,threadName,pid,key,args){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);if(kthread.openAsyncSlices){var slice=kthread.openAsyncSlices[key];if(slice){slice.duration=ts-slice.start;slice.args=args;slice.endThread=kthread.thread;slice.subSlices=[new tr.model.AsyncSlice(category,slice.title,slice.colorId,slice.start,slice.args,slice.duration)];kthread.thread.asyncSliceGroup.push(slice);delete kthread.openAsyncSlices[key];}}},f2fsWriteBeginEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/dev = \((\d+,\d+)\), ino = (\d+), pos = (\d+), len = (\d+), flags = (\d+)/.exec(eventBase.details);if(!event)
 return false;var device=event[1];var inode=parseInt(event[2]);var pos=parseInt(event[3]);var len=parseInt(event[4]);var key=device+'-'+inode+'-'+pos+'-'+len;this.openAsyncSlice(ts,'f2fs',eventBase.threadName,eventBase.pid,key,'f2fs_write');return true;},f2fsWriteEndEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/dev = \((\d+,\d+)\), ino = (\d+), pos = (\d+), len = (\d+), copied = (\d+)/.exec(eventBase.details);if(!event)
 return false;var device=event[1];var inode=parseInt(event[2]);var pos=parseInt(event[3]);var len=parseInt(event[4]);var error=parseInt(event[5])!==len;var key=device+'-'+inode+'-'+pos+'-'+len;this.closeAsyncSlice(ts,'f2fs',eventBase.threadName,eventBase.pid,key,{device:device,inode:inode,error:error});return true;},ext4WriteBeginEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) flags (\d+)/.exec(eventBase.details);if(!event)
 return false;var device=event[1];var inode=parseInt(event[2]);var pos=parseInt(event[3]);var len=parseInt(event[4]);var key=device+'-'+inode+'-'+pos+'-'+len;this.openAsyncSlice(ts,'ext4',eventBase.threadName,eventBase.pid,key,'ext4_write');return true;},ext4WriteEndEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) copied (\d+)/.exec(eventBase.details);if(!event)
@@ -3731,31 +3805,31 @@
 if(event[6]=='S'){action+=' sync';}
 if(event[7]=='M'){action+=' meta';}
 var device=event[1];var sector=parseInt(event[8]);var numSectors=parseInt(event[9]);var key=device+'-'+sector+'-'+numSectors;this.openAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,action);return true;},blockRqCompleteEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? '+'\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);if(!event)
-return false;var device=event[1];var sector=parseInt(event[8]);var numSectors=parseInt(event[9]);var error=parseInt(event[10]);var key=device+'-'+sector+'-'+numSectors;this.closeAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,{device:device,sector:sector,numSectors:numSectors,error:error});return true;}};Parser.register(DiskParser);return{DiskParser:DiskParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function DrmParser(importer){Parser.call(this,importer);importer.registerEventHandler('drm_vblank_event',DrmParser.prototype.vblankEvent.bind(this));}
-DrmParser.prototype={__proto__:Parser.prototype,drmVblankSlice:function(ts,eventName,args){var kthread=this.importer.getOrCreatePseudoThread('drm_vblank');kthread.openSlice=eventName;var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},vblankEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/crtc=(\d+), seq=(\d+)/.exec(eventBase.details);if(!event)
-return false;var crtc=parseInt(event[1]);var seq=parseInt(event[2]);this.drmVblankSlice(ts,'vblank:'+crtc,{crtc:crtc,seq:seq});return true;}};Parser.register(DrmParser);return{DrmParser:DrmParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function IrqParser(importer){Parser.call(this,importer);importer.registerEventHandler('irq_handler_entry',IrqParser.prototype.irqHandlerEntryEvent.bind(this));importer.registerEventHandler('irq_handler_exit',IrqParser.prototype.irqHandlerExitEvent.bind(this));importer.registerEventHandler('softirq_raise',IrqParser.prototype.softirqRaiseEvent.bind(this));importer.registerEventHandler('softirq_entry',IrqParser.prototype.softirqEntryEvent.bind(this));importer.registerEventHandler('softirq_exit',IrqParser.prototype.softirqExitEvent.bind(this));}
+return false;var device=event[1];var sector=parseInt(event[8]);var numSectors=parseInt(event[9]);var error=parseInt(event[10]);var key=device+'-'+sector+'-'+numSectors;this.closeAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,{device:device,sector:sector,numSectors:numSectors,error:error});return true;}};Parser.register(DiskParser);return{DiskParser:DiskParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function DrmParser(importer){Parser.call(this,importer);importer.registerEventHandler('drm_vblank_event',DrmParser.prototype.vblankEvent.bind(this));}
+DrmParser.prototype={__proto__:Parser.prototype,drmVblankSlice:function(ts,eventName,args){var kthread=this.importer.getOrCreatePseudoThread('drm_vblank');kthread.openSlice=eventName;var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},vblankEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/crtc=(\d+), seq=(\d+)/.exec(eventBase.details);if(!event)
+return false;var crtc=parseInt(event[1]);var seq=parseInt(event[2]);this.drmVblankSlice(ts,'vblank:'+crtc,{crtc:crtc,seq:seq});return true;}};Parser.register(DrmParser);return{DrmParser:DrmParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function IrqParser(importer){Parser.call(this,importer);importer.registerEventHandler('irq_handler_entry',IrqParser.prototype.irqHandlerEntryEvent.bind(this));importer.registerEventHandler('irq_handler_exit',IrqParser.prototype.irqHandlerExitEvent.bind(this));importer.registerEventHandler('softirq_raise',IrqParser.prototype.softirqRaiseEvent.bind(this));importer.registerEventHandler('softirq_entry',IrqParser.prototype.softirqEntryEvent.bind(this));importer.registerEventHandler('softirq_exit',IrqParser.prototype.softirqExitEvent.bind(this));}
 var irqHandlerEntryRE=/irq=(\d+) name=(.+)/;var irqHandlerExitRE=/irq=(\d+) ret=(.+)/;var softirqRE=/vec=(\d+) \[action=(.+)\]/;IrqParser.prototype={__proto__:Parser.prototype,irqHandlerEntryEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=irqHandlerEntryRE.exec(eventBase.details);if(!event)
 return false;var irq=parseInt(event[1]);var name=event[2];var thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);thread.lastEntryTs=ts;thread.irqName=name;return true;},irqHandlerExitEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=irqHandlerExitRE.exec(eventBase.details);if(!event)
-return false;var irq=parseInt(event[1]);var ret=event[2];var thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){var duration=ts-thread.lastEntryTs;var slice=new tv.c.trace_model.Slice('',thread.irqName,tv.b.ui.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{ret:ret},duration);thread.thread.sliceGroup.pushSlice(slice);}
+return false;var irq=parseInt(event[1]);var ret=event[2];var thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){var duration=ts-thread.lastEntryTs;var slice=new tr.model.Slice('',thread.irqName,tr.b.ui.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{ret:ret},duration);thread.thread.sliceGroup.pushSlice(slice);}
 thread.lastEntryTs=undefined;thread.irqName=undefined;return true;},softirqRaiseEvent:function(eventName,cpuNumber,pid,ts,eventBase){return true;},softirqEntryEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=softirqRE.exec(eventBase.details);if(!event)
 return false;var action=event[2];var thread=this.importer.getOrCreatePseudoThread('softirq cpu '+cpuNumber);thread.lastEntryTs=ts;return true;},softirqExitEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=softirqRE.exec(eventBase.details);if(!event)
-return false;var vec=parseInt(event[1]);var action=event[2];var thread=this.importer.getOrCreatePseudoThread('softirq cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){var duration=ts-thread.lastEntryTs;var slice=new tv.c.trace_model.Slice('',action,tv.b.ui.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{vec:vec},duration);thread.thread.sliceGroup.pushSlice(slice);}
-thread.lastEntryTs=undefined;return true;}};Parser.register(IrqParser);return{IrqParser:IrqParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function ExynosParser(importer){Parser.call(this,importer);importer.registerEventHandler('exynos_busfreq_target_int',ExynosParser.prototype.busfreqTargetIntEvent.bind(this));importer.registerEventHandler('exynos_busfreq_target_mif',ExynosParser.prototype.busfreqTargetMifEvent.bind(this));importer.registerEventHandler('exynos_page_flip_state',ExynosParser.prototype.pageFlipStateEvent.bind(this));}
-ExynosParser.prototype={__proto__:Parser.prototype,exynosBusfreqSample:function(name,ts,frequency){var targetCpu=this.importer.getOrCreateCpu(0);var counter=targetCpu.getOrCreateCounter('',name);if(counter.numSeries===0){counter.addSeries(new tv.c.trace_model.CounterSeries('frequency',tv.b.ui.getColorIdForGeneralPurposeString(counter.name+'.'+'frequency')));}
+return false;var vec=parseInt(event[1]);var action=event[2];var thread=this.importer.getOrCreatePseudoThread('softirq cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){var duration=ts-thread.lastEntryTs;var slice=new tr.model.Slice('',action,tr.b.ui.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{vec:vec},duration);thread.thread.sliceGroup.pushSlice(slice);}
+thread.lastEntryTs=undefined;return true;}};Parser.register(IrqParser);return{IrqParser:IrqParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function ExynosParser(importer){Parser.call(this,importer);importer.registerEventHandler('exynos_busfreq_target_int',ExynosParser.prototype.busfreqTargetIntEvent.bind(this));importer.registerEventHandler('exynos_busfreq_target_mif',ExynosParser.prototype.busfreqTargetMifEvent.bind(this));importer.registerEventHandler('exynos_page_flip_state',ExynosParser.prototype.pageFlipStateEvent.bind(this));}
+ExynosParser.prototype={__proto__:Parser.prototype,exynosBusfreqSample:function(name,ts,frequency){var targetCpu=this.importer.getOrCreateCpu(0);var counter=targetCpu.getOrCreateCounter('',name);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries('frequency',tr.b.ui.getColorIdForGeneralPurposeString(counter.name+'.'+'frequency')));}
 counter.series.forEach(function(series){series.addCounterSample(ts,frequency);});},busfreqTargetIntEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/frequency=(\d+)/.exec(eventBase.details);if(!event)
 return false;this.exynosBusfreqSample('INT Frequency',ts,parseInt(event[1]));return true;},busfreqTargetMifEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/frequency=(\d+)/.exec(eventBase.details);if(!event)
-return false;this.exynosBusfreqSample('MIF Frequency',ts,parseInt(event[1]));return true;},exynosPageFlipStateOpenSlice:function(ts,pipe,fb,state){var kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');kthread.openSliceTS=ts;kthread.openSlice=state;},exynosPageFlipStateCloseSlice:function(ts,pipe,fb,args){var kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');if(kthread.openSlice){var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+return false;this.exynosBusfreqSample('MIF Frequency',ts,parseInt(event[1]));return true;},exynosPageFlipStateOpenSlice:function(ts,pipe,fb,state){var kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');kthread.openSliceTS=ts;kthread.openSlice=state;},exynosPageFlipStateCloseSlice:function(ts,pipe,fb,args){var kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');if(kthread.openSlice){var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
 kthread.openSlice=undefined;},pageFlipStateEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/pipe=(\d+), fb=(\d+), state=(.*)/.exec(eventBase.details);if(!event)
 return false;var pipe=parseInt(event[1]);var fb=parseInt(event[2]);var state=event[3];this.exynosPageFlipStateCloseSlice(ts,pipe,fb,{pipe:pipe,fb:fb});if(state!=='flipped')
-this.exynosPageFlipStateOpenSlice(ts,pipe,fb,state);return true;}};Parser.register(ExynosParser);return{ExynosParser:ExynosParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function GestureParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:log',GestureParser.prototype.logEvent.bind(this));importer.registerEventHandler('tracing_mark_write:SyncInterpret',GestureParser.prototype.syncEvent.bind(this));importer.registerEventHandler('tracing_mark_write:HandleTimer',GestureParser.prototype.timerEvent.bind(this));}
+this.exynosPageFlipStateOpenSlice(ts,pipe,fb,state);return true;}};Parser.register(ExynosParser);return{ExynosParser:ExynosParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function GestureParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:log',GestureParser.prototype.logEvent.bind(this));importer.registerEventHandler('tracing_mark_write:SyncInterpret',GestureParser.prototype.syncEvent.bind(this));importer.registerEventHandler('tracing_mark_write:HandleTimer',GestureParser.prototype.timerEvent.bind(this));}
 GestureParser.prototype={__proto__:Parser.prototype,gestureOpenSlice:function(title,ts,opt_args){var thread=this.importer.getOrCreatePseudoThread('gesture').thread;thread.sliceGroup.beginSlice('touchpad_gesture',title,ts,opt_args);},gestureCloseSlice:function(title,ts){var thread=this.importer.getOrCreatePseudoThread('gesture').thread;if(thread.sliceGroup.openSliceCount){var slice=thread.sliceGroup.mostRecentlyOpenedPartialSlice;if(slice.title!=title){this.importer.model.importWarning({type:'title_match_error',message:'Titles do not match. Title is '+
 slice.title+' in openSlice, and is '+
 title+' in endSlice'});}else{thread.sliceGroup.endSlice(ts);}}},logEvent:function(eventName,cpuNumber,pid,ts,eventBase){var innerEvent=/^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);switch(innerEvent[1]){case'start':this.gestureOpenSlice('GestureLog',ts,{name:innerEvent[2]});break;case'end':this.gestureCloseSlice('GestureLog',ts);}
 return true;},syncEvent:function(eventName,cpuNumber,pid,ts,eventBase){var innerEvent=/^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);switch(innerEvent[1]){case'start':this.gestureOpenSlice('SyncInterpret',ts,{interpreter:innerEvent[2]});break;case'end':this.gestureCloseSlice('SyncInterpret',ts);}
 return true;},timerEvent:function(eventName,cpuNumber,pid,ts,eventBase){var innerEvent=/^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);switch(innerEvent[1]){case'start':this.gestureOpenSlice('HandleTimer',ts,{interpreter:innerEvent[2]});break;case'end':this.gestureCloseSlice('HandleTimer',ts);}
-return true;}};Parser.register(GestureParser);return{GestureParser:GestureParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function I915Parser(importer){Parser.call(this,importer);importer.registerEventHandler('i915_gem_object_create',I915Parser.prototype.gemObjectCreateEvent.bind(this));importer.registerEventHandler('i915_gem_object_bind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_unbind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_change_domain',I915Parser.prototype.gemObjectChangeDomainEvent.bind(this));importer.registerEventHandler('i915_gem_object_pread',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_pwrite',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_fault',I915Parser.prototype.gemObjectFaultEvent.bind(this));importer.registerEventHandler('i915_gem_object_clflush',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_object_destroy',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_ring_dispatch',I915Parser.prototype.gemRingDispatchEvent.bind(this));importer.registerEventHandler('i915_gem_ring_flush',I915Parser.prototype.gemRingFlushEvent.bind(this));importer.registerEventHandler('i915_gem_request',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_add',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_complete',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_retire',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_begin',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_end',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_begin',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_end',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_reg_rw',I915Parser.prototype.regRWEvent.bind(this));importer.registerEventHandler('i915_flip_request',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('i915_flip_complete',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('intel_gpu_freq_change',I915Parser.prototype.gpuFrequency.bind(this));}
-I915Parser.prototype={__proto__:Parser.prototype,i915FlipOpenSlice:function(ts,obj,plane){var kthread=this.importer.getOrCreatePseudoThread('i915_flip');kthread.openSliceTS=ts;kthread.openSlice='flip:'+obj+'/'+plane;},i915FlipCloseSlice:function(ts,args){var kthread=this.importer.getOrCreatePseudoThread('i915_flip');if(kthread.openSlice){var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
-kthread.openSlice=undefined;},i915GemObjectSlice:function(ts,eventName,obj,args){var kthread=this.importer.getOrCreatePseudoThread('i915_gem');kthread.openSlice=eventName+':'+obj;var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915GemRingSlice:function(ts,eventName,dev,ring,args){var kthread=this.importer.getOrCreatePseudoThread('i915_gem_ring');kthread.openSlice=eventName+':'+dev+'.'+ring;var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915RegSlice:function(ts,eventName,reg,args){var kthread=this.importer.getOrCreatePseudoThread('i915_reg');kthread.openSlice=eventName+':'+reg;var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915FreqChangeSlice:function(ts,eventName,args){var kthread=this.importer.getOrCreatePseudoThread('i915_gpu_freq');kthread.openSlice=eventName;var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},gemObjectCreateEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/obj=(\w+), size=(\d+)/.exec(eventBase.details);if(!event)
+return true;}};Parser.register(GestureParser);return{GestureParser:GestureParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function I915Parser(importer){Parser.call(this,importer);importer.registerEventHandler('i915_gem_object_create',I915Parser.prototype.gemObjectCreateEvent.bind(this));importer.registerEventHandler('i915_gem_object_bind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_unbind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_change_domain',I915Parser.prototype.gemObjectChangeDomainEvent.bind(this));importer.registerEventHandler('i915_gem_object_pread',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_pwrite',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_fault',I915Parser.prototype.gemObjectFaultEvent.bind(this));importer.registerEventHandler('i915_gem_object_clflush',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_object_destroy',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_ring_dispatch',I915Parser.prototype.gemRingDispatchEvent.bind(this));importer.registerEventHandler('i915_gem_ring_flush',I915Parser.prototype.gemRingFlushEvent.bind(this));importer.registerEventHandler('i915_gem_request',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_add',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_complete',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_retire',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_begin',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_end',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_begin',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_end',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_reg_rw',I915Parser.prototype.regRWEvent.bind(this));importer.registerEventHandler('i915_flip_request',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('i915_flip_complete',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('intel_gpu_freq_change',I915Parser.prototype.gpuFrequency.bind(this));}
+I915Parser.prototype={__proto__:Parser.prototype,i915FlipOpenSlice:function(ts,obj,plane){var kthread=this.importer.getOrCreatePseudoThread('i915_flip');kthread.openSliceTS=ts;kthread.openSlice='flip:'+obj+'/'+plane;},i915FlipCloseSlice:function(ts,args){var kthread=this.importer.getOrCreatePseudoThread('i915_flip');if(kthread.openSlice){var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+kthread.openSlice=undefined;},i915GemObjectSlice:function(ts,eventName,obj,args){var kthread=this.importer.getOrCreatePseudoThread('i915_gem');kthread.openSlice=eventName+':'+obj;var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915GemRingSlice:function(ts,eventName,dev,ring,args){var kthread=this.importer.getOrCreatePseudoThread('i915_gem_ring');kthread.openSlice=eventName+':'+dev+'.'+ring;var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915RegSlice:function(ts,eventName,reg,args){var kthread=this.importer.getOrCreatePseudoThread('i915_reg');kthread.openSlice=eventName+':'+reg;var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915FreqChangeSlice:function(ts,eventName,args){var kthread=this.importer.getOrCreatePseudoThread('i915_gpu_freq');kthread.openSlice=eventName;var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},gemObjectCreateEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/obj=(\w+), size=(\d+)/.exec(eventBase.details);if(!event)
 return false;var obj=event[1];var size=parseInt(event[2]);this.i915GemObjectSlice(ts,eventName,obj,{obj:obj,size:size});return true;},gemObjectBindEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/obj=(\w+), offset=(\w+), size=(\d+)/.exec(eventBase.details);if(!event)
 return false;var obj=event[1];var offset=event[2];var size=parseInt(event[3]);this.i915ObjectGemSlice(ts,eventName+':'+obj,{obj:obj,offset:offset,size:size});return true;},gemObjectChangeDomainEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/obj=(\w+), read=(\w+=>\w+), write=(\w+=>\w+)/.exec(eventBase.details);if(!event)
 return false;var obj=event[1];var read=event[2];var write=event[3];this.i915GemObjectSlice(ts,eventName,obj,{obj:obj,read:read,write:write});return true;},gemObjectPreadWriteEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/obj=(\w+), offset=(\d+), len=(\d+)/.exec(eventBase.details);if(!event)
@@ -3770,7 +3844,7 @@
 return false;var plane=parseInt(event[1]);var obj=event[2];if(eventName=='i915_flip_request')
 this.i915FlipOpenSlice(ts,obj,plane);else
 this.i915FlipCloseSlice(ts,{obj:obj,plane:plane});return true;},gpuFrequency:function(eventName,cpuNumver,pid,ts,eventBase){var event=/new_freq=(\d+)/.exec(eventBase.details);if(!event)
-return false;var freq=parseInt(event[1]);this.i915FreqChangeSlice(ts,eventName,{freq:freq});return true;}};Parser.register(I915Parser);return{I915Parser:I915Parser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function MaliParser(importer){Parser.call(this,importer);importer.registerEventHandler('mali_dvfs_event',MaliParser.prototype.dvfsEventEvent.bind(this));importer.registerEventHandler('mali_dvfs_set_clock',MaliParser.prototype.dvfsSetClockEvent.bind(this));importer.registerEventHandler('mali_dvfs_set_voltage',MaliParser.prototype.dvfsSetVoltageEvent.bind(this));this.addJMCounter('mali_hwc_MESSAGES_SENT','Messages Sent');this.addJMCounter('mali_hwc_MESSAGES_RECEIVED','Messages Received');this.addJMCycles('mali_hwc_GPU_ACTIVE','GPU Active');this.addJMCycles('mali_hwc_IRQ_ACTIVE','IRQ Active');for(var i=0;i<7;i++){var jobStr='JS'+i;var jobHWCStr='mali_hwc_'+jobStr;this.addJMCounter(jobHWCStr+'_JOBS',jobStr+' Jobs');this.addJMCounter(jobHWCStr+'_TASKS',jobStr+' Tasks');this.addJMCycles(jobHWCStr+'_ACTIVE',jobStr+' Active');this.addJMCycles(jobHWCStr+'_WAIT_READ',jobStr+' Wait Read');this.addJMCycles(jobHWCStr+'_WAIT_ISSUE',jobStr+' Wait Issue');this.addJMCycles(jobHWCStr+'_WAIT_DEPEND',jobStr+' Wait Depend');this.addJMCycles(jobHWCStr+'_WAIT_FINISH',jobStr+' Wait Finish');}
+return false;var freq=parseInt(event[1]);this.i915FreqChangeSlice(ts,eventName,{freq:freq});return true;}};Parser.register(I915Parser);return{I915Parser:I915Parser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function MaliParser(importer){Parser.call(this,importer);importer.registerEventHandler('mali_dvfs_event',MaliParser.prototype.dvfsEventEvent.bind(this));importer.registerEventHandler('mali_dvfs_set_clock',MaliParser.prototype.dvfsSetClockEvent.bind(this));importer.registerEventHandler('mali_dvfs_set_voltage',MaliParser.prototype.dvfsSetVoltageEvent.bind(this));this.addJMCounter('mali_hwc_MESSAGES_SENT','Messages Sent');this.addJMCounter('mali_hwc_MESSAGES_RECEIVED','Messages Received');this.addJMCycles('mali_hwc_GPU_ACTIVE','GPU Active');this.addJMCycles('mali_hwc_IRQ_ACTIVE','IRQ Active');for(var i=0;i<7;i++){var jobStr='JS'+i;var jobHWCStr='mali_hwc_'+jobStr;this.addJMCounter(jobHWCStr+'_JOBS',jobStr+' Jobs');this.addJMCounter(jobHWCStr+'_TASKS',jobStr+' Tasks');this.addJMCycles(jobHWCStr+'_ACTIVE',jobStr+' Active');this.addJMCycles(jobHWCStr+'_WAIT_READ',jobStr+' Wait Read');this.addJMCycles(jobHWCStr+'_WAIT_ISSUE',jobStr+' Wait Issue');this.addJMCycles(jobHWCStr+'_WAIT_DEPEND',jobStr+' Wait Depend');this.addJMCycles(jobHWCStr+'_WAIT_FINISH',jobStr+' Wait Finish');}
 this.addTilerCounter('mali_hwc_TRIANGLES','Triangles');this.addTilerCounter('mali_hwc_QUADS','Quads');this.addTilerCounter('mali_hwc_POLYGONS','Polygons');this.addTilerCounter('mali_hwc_POINTS','Points');this.addTilerCounter('mali_hwc_LINES','Lines');this.addTilerCounter('mali_hwc_VCACHE_HIT','VCache Hit');this.addTilerCounter('mali_hwc_VCACHE_MISS','VCache Miss');this.addTilerCounter('mali_hwc_FRONT_FACING','Front Facing');this.addTilerCounter('mali_hwc_BACK_FACING','Back Facing');this.addTilerCounter('mali_hwc_PRIM_VISIBLE','Prim Visible');this.addTilerCounter('mali_hwc_PRIM_CULLED','Prim Culled');this.addTilerCounter('mali_hwc_PRIM_CLIPPED','Prim Clipped');this.addTilerCounter('mali_hwc_WRBUF_HIT','Wrbuf Hit');this.addTilerCounter('mali_hwc_WRBUF_MISS','Wrbuf Miss');this.addTilerCounter('mali_hwc_WRBUF_LINE','Wrbuf Line');this.addTilerCounter('mali_hwc_WRBUF_PARTIAL','Wrbuf Partial');this.addTilerCounter('mali_hwc_WRBUF_STALL','Wrbuf Stall');this.addTilerCycles('mali_hwc_ACTIVE','Tiler Active');this.addTilerCycles('mali_hwc_INDEX_WAIT','Index Wait');this.addTilerCycles('mali_hwc_INDEX_RANGE_WAIT','Index Range Wait');this.addTilerCycles('mali_hwc_VERTEX_WAIT','Vertex Wait');this.addTilerCycles('mali_hwc_PCACHE_WAIT','Pcache Wait');this.addTilerCycles('mali_hwc_WRBUF_WAIT','Wrbuf Wait');this.addTilerCycles('mali_hwc_BUS_READ','Bus Read');this.addTilerCycles('mali_hwc_BUS_WRITE','Bus Write');this.addTilerCycles('mali_hwc_TILER_UTLB_STALL','Tiler UTLB Stall');this.addTilerCycles('mali_hwc_TILER_UTLB_HIT','Tiler UTLB Hit');this.addFragCycles('mali_hwc_FRAG_ACTIVE','Active');this.addFragCounter('mali_hwc_FRAG_PRIMATIVES','Primitives');this.addFragCounter('mali_hwc_FRAG_PRIMATIVES_DROPPED','Primitives Dropped');this.addFragCycles('mali_hwc_FRAG_CYCLE_DESC','Descriptor Processing');this.addFragCycles('mali_hwc_FRAG_CYCLES_PLR','PLR Processing??');this.addFragCycles('mali_hwc_FRAG_CYCLES_VERT','Vertex Processing');this.addFragCycles('mali_hwc_FRAG_CYCLES_TRISETUP','Triangle Setup');this.addFragCycles('mali_hwc_FRAG_CYCLES_RAST','Rasterization???');this.addFragCounter('mali_hwc_FRAG_THREADS','Threads');this.addFragCounter('mali_hwc_FRAG_DUMMY_THREADS','Dummy Threads');this.addFragCounter('mali_hwc_FRAG_QUADS_RAST','Quads Rast');this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_TEST','Quads EZS Test');this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_KILLED','Quads EZS Killed');this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_TEST','Quads LZS Test');this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_KILLED','Quads LZS Killed');this.addFragCycles('mali_hwc_FRAG_CYCLE_NO_TILE','No Tiles');this.addFragCounter('mali_hwc_FRAG_NUM_TILES','Tiles');this.addFragCounter('mali_hwc_FRAG_TRANS_ELIM','Transactions Eliminated');this.addComputeCycles('mali_hwc_COMPUTE_ACTIVE','Active');this.addComputeCounter('mali_hwc_COMPUTE_TASKS','Tasks');this.addComputeCounter('mali_hwc_COMPUTE_THREADS','Threads Started');this.addComputeCycles('mali_hwc_COMPUTE_CYCLES_DESC','Waiting for Descriptors');this.addTripipeCycles('mali_hwc_TRIPIPE_ACTIVE','Active');this.addArithCounter('mali_hwc_ARITH_WORDS','Instructions (/Pipes)');this.addArithCycles('mali_hwc_ARITH_CYCLES_REG','Reg scheduling stalls (/Pipes)');this.addArithCycles('mali_hwc_ARITH_CYCLES_L0','L0 cache miss stalls (/Pipes)');this.addArithCounter('mali_hwc_ARITH_FRAG_DEPEND','Frag dep check failures (/Pipes)');this.addLSCounter('mali_hwc_LS_WORDS','Instruction Words Completed');this.addLSCounter('mali_hwc_LS_ISSUES','Full Pipeline Issues');this.addLSCounter('mali_hwc_LS_RESTARTS','Restarts (unpairable insts)');this.addLSCounter('mali_hwc_LS_REISSUES_MISS','Pipeline reissue (cache miss/uTLB)');this.addLSCounter('mali_hwc_LS_REISSUES_VD','Pipeline reissue (varying data)');this.addLSCounter('mali_hwc_LS_REISSUE_ATTRIB_MISS','Pipeline reissue (attribute cache miss)');this.addLSCounter('mali_hwc_LS_REISSUE_NO_WB','Writeback not used');this.addTexCounter('mali_hwc_TEX_WORDS','Words');this.addTexCounter('mali_hwc_TEX_BUBBLES','Bubbles');this.addTexCounter('mali_hwc_TEX_WORDS_L0','Words L0');this.addTexCounter('mali_hwc_TEX_WORDS_DESC','Words Desc');this.addTexCounter('mali_hwc_TEX_THREADS','Threads');this.addTexCounter('mali_hwc_TEX_RECIRC_FMISS','Recirc due to Full Miss');this.addTexCounter('mali_hwc_TEX_RECIRC_DESC','Recirc due to Desc Miss');this.addTexCounter('mali_hwc_TEX_RECIRC_MULTI','Recirc due to Multipass');this.addTexCounter('mali_hwc_TEX_RECIRC_PMISS','Recirc due to Partial Cache Miss');this.addTexCounter('mali_hwc_TEX_RECIRC_CONF','Recirc due to Cache Conflict');this.addLSCCounter('mali_hwc_LSC_READ_HITS','Read Hits');this.addLSCCounter('mali_hwc_LSC_READ_MISSES','Read Misses');this.addLSCCounter('mali_hwc_LSC_WRITE_HITS','Write Hits');this.addLSCCounter('mali_hwc_LSC_WRITE_MISSES','Write Misses');this.addLSCCounter('mali_hwc_LSC_ATOMIC_HITS','Atomic Hits');this.addLSCCounter('mali_hwc_LSC_ATOMIC_MISSES','Atomic Misses');this.addLSCCounter('mali_hwc_LSC_LINE_FETCHES','Line Fetches');this.addLSCCounter('mali_hwc_LSC_DIRTY_LINE','Dirty Lines');this.addLSCCounter('mali_hwc_LSC_SNOOPS','Snoops');this.addAXICounter('mali_hwc_AXI_TLB_STALL','Address channel stall');this.addAXICounter('mali_hwc_AXI_TLB_MISS','Cache Miss');this.addAXICounter('mali_hwc_AXI_TLB_TRANSACTION','Transactions');this.addAXICounter('mali_hwc_LS_TLB_MISS','LS Cache Miss');this.addAXICounter('mali_hwc_LS_TLB_HIT','LS Cache Hit');this.addAXICounter('mali_hwc_AXI_BEATS_READ','Read Beats');this.addAXICounter('mali_hwc_AXI_BEATS_WRITE','Write Beats');this.addMMUCounter('mali_hwc_MMU_TABLE_WALK','Page Table Walks');this.addMMUCounter('mali_hwc_MMU_REPLAY_MISS','Cache Miss from Replay Buffer');this.addMMUCounter('mali_hwc_MMU_REPLAY_FULL','Replay Buffer Full');this.addMMUCounter('mali_hwc_MMU_NEW_MISS','Cache Miss on New Request');this.addMMUCounter('mali_hwc_MMU_HIT','Cache Hit');this.addMMUCycles('mali_hwc_UTLB_STALL','UTLB Stalled');this.addMMUCycles('mali_hwc_UTLB_REPLAY_MISS','UTLB Replay Miss');this.addMMUCycles('mali_hwc_UTLB_REPLAY_FULL','UTLB Replay Full');this.addMMUCycles('mali_hwc_UTLB_NEW_MISS','UTLB New Miss');this.addMMUCycles('mali_hwc_UTLB_HIT','UTLB Hit');this.addL2Counter('mali_hwc_L2_READ_BEATS','Read Beats');this.addL2Counter('mali_hwc_L2_WRITE_BEATS','Write Beats');this.addL2Counter('mali_hwc_L2_ANY_LOOKUP','Any Lookup');this.addL2Counter('mali_hwc_L2_READ_LOOKUP','Read Lookup');this.addL2Counter('mali_hwc_L2_SREAD_LOOKUP','Shareable Read Lookup');this.addL2Counter('mali_hwc_L2_READ_REPLAY','Read Replayed');this.addL2Counter('mali_hwc_L2_READ_SNOOP','Read Snoop');this.addL2Counter('mali_hwc_L2_READ_HIT','Read Cache Hit');this.addL2Counter('mali_hwc_L2_CLEAN_MISS','CleanUnique Miss');this.addL2Counter('mali_hwc_L2_WRITE_LOOKUP','Write Lookup');this.addL2Counter('mali_hwc_L2_SWRITE_LOOKUP','Shareable Write Lookup');this.addL2Counter('mali_hwc_L2_WRITE_REPLAY','Write Replayed');this.addL2Counter('mali_hwc_L2_WRITE_SNOOP','Write Snoop');this.addL2Counter('mali_hwc_L2_WRITE_HIT','Write Cache Hit');this.addL2Counter('mali_hwc_L2_EXT_READ_FULL','ExtRD with BIU Full');this.addL2Counter('mali_hwc_L2_EXT_READ_HALF','ExtRD with BIU >1/2 Full');this.addL2Counter('mali_hwc_L2_EXT_WRITE_FULL','ExtWR with BIU Full');this.addL2Counter('mali_hwc_L2_EXT_WRITE_HALF','ExtWR with BIU >1/2 Full');this.addL2Counter('mali_hwc_L2_EXT_READ','External Read (ExtRD)');this.addL2Counter('mali_hwc_L2_EXT_READ_LINE','ExtRD (linefill)');this.addL2Counter('mali_hwc_L2_EXT_WRITE','External Write (ExtWR)');this.addL2Counter('mali_hwc_L2_EXT_WRITE_LINE','ExtWR (linefill)');this.addL2Counter('mali_hwc_L2_EXT_WRITE_SMALL','ExtWR (burst size <64B)');this.addL2Counter('mali_hwc_L2_EXT_BARRIER','External Barrier');this.addL2Counter('mali_hwc_L2_EXT_AR_STALL','Address Read stalls');this.addL2Counter('mali_hwc_L2_EXT_R_BUF_FULL','Response Buffer full stalls');this.addL2Counter('mali_hwc_L2_EXT_RD_BUF_FULL','Read Data Buffer full stalls');this.addL2Counter('mali_hwc_L2_EXT_R_RAW','RAW hazard stalls');this.addL2Counter('mali_hwc_L2_EXT_W_STALL','Write Data stalls');this.addL2Counter('mali_hwc_L2_EXT_W_BUF_FULL','Write Data Buffer full');this.addL2Counter('mali_hwc_L2_EXT_R_W_HAZARD','WAW or WAR hazard stalls');this.addL2Counter('mali_hwc_L2_TAG_HAZARD','Tag hazard replays');this.addL2Cycles('mali_hwc_L2_SNOOP_FULL','Snoop buffer full');this.addL2Cycles('mali_hwc_L2_REPLAY_FULL','Replay buffer full');importer.registerEventHandler('tracing_mark_write:mali_driver',MaliParser.prototype.maliDDKEvent.bind(this));this.model_=importer.model_;}
 MaliParser.prototype={__proto__:Parser.prototype,maliDDKOpenSlice:function(pid,tid,ts,func,blockinfo){var thread=this.importer.model_.getOrCreateProcess(pid).getOrCreateThread(tid);var funcArgs=/^([\w\d_]*)(?:\(\))?:?\s*(.*)$/.exec(func);thread.sliceGroup.beginSlice('gpu-driver',funcArgs[1],ts,{'args':funcArgs[2],'blockinfo':blockinfo});},maliDDKCloseSlice:function(pid,tid,ts,args,blockinfo){var thread=this.importer.model_.getOrCreateProcess(pid).getOrCreateThread(tid);if(!thread.sliceGroup.openSliceCount){return;}
 thread.sliceGroup.endSlice(ts);},autoDetectLineRE:function(line){var lineREWithThread=/^\s*\(([\w\-]*)\)\s*(\w+):\s*([\w\\\/\.\-]*@\d*):?\s*(.*)$/;if(lineREWithThread.test(line))
@@ -3778,12 +3852,12 @@
 return lineRENoThread;return null;},lineRE:null,maliDDKEvent:function(eventName,cpuNumber,pid,ts,eventBase){if(this.lineRE==null){this.lineRE=this.autoDetectLineRE(eventBase.details);if(this.lineRE==null)
 return false;}
 var maliEvent=this.lineRE.exec(eventBase.details);var tid=(maliEvent[1]===''?'mali':maliEvent[1]);switch(maliEvent[2]){case'cros_trace_print_enter':this.maliDDKOpenSlice(pid,tid,ts,maliEvent[4],maliEvent[3]);break;case'cros_trace_print_exit':this.maliDDKCloseSlice(pid,tid,ts,[],maliEvent[3]);}
-return true;},dvfsSample:function(counterName,seriesName,ts,s){var value=parseInt(s);var counter=this.model_.kernel.getOrCreateCounter('DVFS',counterName);if(counter.numSeries===0){counter.addSeries(new tv.c.trace_model.CounterSeries(seriesName,tv.b.ui.getColorIdForGeneralPurposeString(counter.name)));}
+return true;},dvfsSample:function(counterName,seriesName,ts,s){var value=parseInt(s);var counter=this.model_.kernel.getOrCreateCounter('DVFS',counterName);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries(seriesName,tr.b.ui.getColorIdForGeneralPurposeString(counter.name)));}
 counter.series.forEach(function(series){series.addCounterSample(ts,value);});},dvfsEventEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/utilization=(\d+)/.exec(eventBase.details);if(!event)
 return false;this.dvfsSample('DVFS Utilization','utilization',ts,event[1]);return true;},dvfsSetClockEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/frequency=(\d+)/.exec(eventBase.details);if(!event)
 return false;this.dvfsSample('DVFS Frequency','frequency',ts,event[1]);return true;},dvfsSetVoltageEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/voltage=(\d+)/.exec(eventBase.details);if(!event)
 return false;this.dvfsSample('DVFS Voltage','voltage',ts,event[1]);return true;},hwcSample:function(cat,counterName,seriesName,ts,eventBase){var event=/val=(\d+)/.exec(eventBase.details);if(!event)
-return false;var value=parseInt(event[1]);var counter=this.model_.kernel.getOrCreateCounter(cat,counterName);if(counter.numSeries===0){counter.addSeries(new tv.c.trace_model.CounterSeries(seriesName,tv.b.ui.getColorIdForGeneralPurposeString(counter.name)));}
+return false;var value=parseInt(event[1]);var counter=this.model_.kernel.getOrCreateCounter(cat,counterName);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries(seriesName,tr.b.ui.getColorIdForGeneralPurposeString(counter.name)));}
 counter.series.forEach(function(series){series.addCounterSample(ts,value);});return true;},jmSample:function(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:jm','JM: '+ctrName,seriesName,ts,eventBase);},addJMCounter:function(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.jmSample(hwcTitle,'count',ts,eventBase);}
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addJMCycles:function(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.jmSample(hwcTitle,'cycles',ts,eventBase);}
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));},tilerSample:function(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:tiler','Tiler: '+ctrName,seriesName,ts,eventBase);},addTilerCounter:function(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.tilerSample(hwcTitle,'count',ts,eventBase);}
@@ -3803,78 +3877,78 @@
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addMMUCycles:function(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.mmuSample(hwcTitle,'cycles',ts,eventBase);}
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));},l2Sample:function(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:l2','L2: '+ctrName,seriesName,ts,eventBase);},addL2Counter:function(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.l2Sample(hwcTitle,'count',ts,eventBase);}
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addL2Cycles:function(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.l2Sample(hwcTitle,'cycles',ts,eventBase);}
-this.importer.registerEventHandler(hwcEventName,handler.bind(this));}};Parser.register(MaliParser);return{MaliParser:MaliParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function MemReclaimParser(importer){Parser.call(this,importer);importer.registerEventHandler('mm_vmscan_kswapd_wake',MemReclaimParser.prototype.kswapdWake.bind(this));importer.registerEventHandler('mm_vmscan_kswapd_sleep',MemReclaimParser.prototype.kswapdSleep.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_begin',MemReclaimParser.prototype.reclaimBegin.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_end',MemReclaimParser.prototype.reclaimEnd.bind(this));}
-var kswapdWakeRE=/nid=(\d+) order=(\d+)/;var kswapdSleepRE=/nid=(\d+)/;var reclaimBeginRE=/order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;var reclaimEndRE=/nr_reclaimed=(\d+)/;MemReclaimParser.prototype={__proto__:Parser.prototype,openAsyncSlice:function(ts,category,threadName,pid,key,name){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);var slice=new tv.c.trace_model.AsyncSlice(category,name,tv.c.getColorIdForGeneralPurposeString(name),ts);slice.startThread=kthread.thread;if(!kthread.openAsyncSlices){kthread.openAsyncSlices={};}
-kthread.openAsyncSlices[key]=slice;},closeAsyncSlice:function(ts,category,threadName,pid,key,args){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);if(kthread.openAsyncSlices){var slice=kthread.openAsyncSlices[key];if(slice){slice.duration=ts-slice.start;slice.args=args;slice.endThread=kthread.thread;slice.subSlices=[new tv.c.trace_model.Slice(category,slice.title,slice.colorId,slice.start,slice.args,slice.duration)];kthread.thread.asyncSliceGroup.push(slice);delete kthread.openAsyncSlices[key];}}},kswapdWake:function(eventName,cpuNumber,pid,ts,eventBase){var event=kswapdWakeRE.exec(eventBase.details);if(!event)
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));}};Parser.register(MaliParser);return{MaliParser:MaliParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function MemReclaimParser(importer){Parser.call(this,importer);importer.registerEventHandler('mm_vmscan_kswapd_wake',MemReclaimParser.prototype.kswapdWake.bind(this));importer.registerEventHandler('mm_vmscan_kswapd_sleep',MemReclaimParser.prototype.kswapdSleep.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_begin',MemReclaimParser.prototype.reclaimBegin.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_end',MemReclaimParser.prototype.reclaimEnd.bind(this));}
+var kswapdWakeRE=/nid=(\d+) order=(\d+)/;var kswapdSleepRE=/nid=(\d+)/;var reclaimBeginRE=/order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;var reclaimEndRE=/nr_reclaimed=(\d+)/;MemReclaimParser.prototype={__proto__:Parser.prototype,openAsyncSlice:function(ts,category,threadName,pid,key,name){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);var slice=new tr.model.AsyncSlice(category,name,tr.c.getColorIdForGeneralPurposeString(name),ts);slice.startThread=kthread.thread;if(!kthread.openAsyncSlices){kthread.openAsyncSlices={};}
+kthread.openAsyncSlices[key]=slice;},closeAsyncSlice:function(ts,category,threadName,pid,key,args){var kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);if(kthread.openAsyncSlices){var slice=kthread.openAsyncSlices[key];if(slice){slice.duration=ts-slice.start;slice.args=args;slice.endThread=kthread.thread;slice.subSlices=[new tr.model.Slice(category,slice.title,slice.colorId,slice.start,slice.args,slice.duration)];kthread.thread.asyncSliceGroup.push(slice);delete kthread.openAsyncSlices[key];}}},kswapdWake:function(eventName,cpuNumber,pid,ts,eventBase){var event=kswapdWakeRE.exec(eventBase.details);if(!event)
 return false;var nid=parseInt(event[1]);var order=parseInt(event[2]);var kthread=this.importer.getOrCreateKernelThread('kswapd: '+eventBase.threadName,pid,pid);if(kthread.openSliceTS){if(order>kthread.order){kthread.order=order;}}else{kthread.openSliceTS=ts;kthread.order=order;}
-return true;},kswapdSleep:function(eventName,cpuNumber,pid,ts,eventBase){var kthread=this.importer.getOrCreateKernelThread('kswapd: '+eventBase.threadName,pid,pid);if(kthread.openSliceTS){var slice=new tv.c.trace_model.Slice('',eventBase.threadName,tv.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),kthread.openSliceTS,{order:kthread.order},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+return true;},kswapdSleep:function(eventName,cpuNumber,pid,ts,eventBase){var kthread=this.importer.getOrCreateKernelThread('kswapd: '+eventBase.threadName,pid,pid);if(kthread.openSliceTS){var slice=new tr.model.Slice('',eventBase.threadName,tr.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),kthread.openSliceTS,{order:kthread.order},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
 kthread.openSliceTS=undefined;kthread.order=undefined;return true;},reclaimBegin:function(eventName,cpuNumber,pid,ts,eventBase){var event=reclaimBeginRE.exec(eventBase.details);if(!event)
 return false;var order=parseInt(event[1]);var gfp=event[2];var kthread=this.importer.getOrCreateKernelThread('direct reclaim: '+eventBase.threadName,pid,pid);kthread.openSliceTS=ts;kthread.order=order;kthread.gfp=gfp;return true;},reclaimEnd:function(eventName,cpuNumber,pid,ts,eventBase){var event=reclaimEndRE.exec(eventBase.details);if(!event)
-return false;var nr_reclaimed=parseInt(event[1]);var kthread=this.importer.getOrCreateKernelThread('direct reclaim: '+eventBase.threadName,pid,pid);if(kthread.openSliceTS!==undefined){var slice=new tv.c.trace_model.Slice('','direct reclaim',tv.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),kthread.openSliceTS,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nr_reclaimed},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
-kthread.openSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser:MemReclaimParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));}
+return false;var nr_reclaimed=parseInt(event[1]);var kthread=this.importer.getOrCreateKernelThread('direct reclaim: '+eventBase.threadName,pid,pid);if(kthread.openSliceTS!==undefined){var slice=new tr.model.Slice('','direct reclaim',tr.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),kthread.openSliceTS,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nr_reclaimed},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+kthread.openSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser:MemReclaimParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));}
 PowerParser.prototype={__proto__:Parser.prototype,cpuStateSlice:function(ts,targetCpuNumber,eventType,cpuState){var targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);var powerCounter;if(eventType!='1'){this.importer.model.importWarning({type:'parse_error',message:'Don\'t understand power_start events of '+'type '+eventType});return;}
-powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tv.c.trace_model.CounterSeries('state',tv.b.ui.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
-powerCounter.series.forEach(function(series){series.addCounterSample(ts,cpuState);});},cpuIdleSlice:function(ts,targetCpuNumber,cpuState){var targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);var powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tv.c.trace_model.CounterSeries('state',tv.b.ui.getColorIdForGeneralPurposeString(powerCounter.name)));}
-var val=(cpuState!=4294967295?cpuState+1:0);powerCounter.series.forEach(function(series){series.addCounterSample(ts,val);});},cpuFrequencySlice:function(ts,targetCpuNumber,powerState){var targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);var powerCounter=targetCpu.getOrCreateCounter('','Clock Frequency');if(powerCounter.numSeries===0){powerCounter.addSeries(new tv.c.trace_model.CounterSeries('state',tv.b.ui.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
+powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',tr.b.ui.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
+powerCounter.series.forEach(function(series){series.addCounterSample(ts,cpuState);});},cpuIdleSlice:function(ts,targetCpuNumber,cpuState){var targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);var powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',tr.b.ui.getColorIdForGeneralPurposeString(powerCounter.name)));}
+var val=(cpuState!=4294967295?cpuState+1:0);powerCounter.series.forEach(function(series){series.addCounterSample(ts,val);});},cpuFrequencySlice:function(ts,targetCpuNumber,powerState){var targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);var powerCounter=targetCpu.getOrCreateCounter('','Clock Frequency');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',tr.b.ui.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
 powerCounter.series.forEach(function(series){series.addCounterSample(ts,powerState);});},powerStartEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/type=(\d+) state=(\d) cpu_id=(\d)+/.exec(eventBase.details);if(!event)
 return false;var targetCpuNumber=parseInt(event[3]);var cpuState=parseInt(event[2]);this.cpuStateSlice(ts,targetCpuNumber,event[1],cpuState);return true;},powerFrequencyEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/type=(\d+) state=(\d+) cpu_id=(\d)+/.exec(eventBase.details);if(!event)
 return false;var targetCpuNumber=parseInt(event[3]);var powerState=parseInt(event[2]);this.cpuFrequencySlice(ts,targetCpuNumber,powerState);return true;},cpuFrequencyEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/state=(\d+) cpu_id=(\d)+/.exec(eventBase.details);if(!event)
 return false;var targetCpuNumber=parseInt(event[2]);var powerState=parseInt(event[1]);this.cpuFrequencySlice(ts,targetCpuNumber,powerState);return true;},cpuIdleEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/state=(\d+) cpu_id=(\d)+/.exec(eventBase.details);if(!event)
-return false;var targetCpuNumber=parseInt(event[2]);var cpuState=parseInt(event[1]);this.cpuIdleSlice(ts,targetCpuNumber,cpuState);return true;}};Parser.register(PowerParser);return{PowerParser:PowerParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function RegulatorParser(importer){Parser.call(this,importer);importer.registerEventHandler('regulator_enable',RegulatorParser.prototype.regulatorEnableEvent.bind(this));importer.registerEventHandler('regulator_enable_delay',RegulatorParser.prototype.regulatorEnableDelayEvent.bind(this));importer.registerEventHandler('regulator_enable_complete',RegulatorParser.prototype.regulatorEnableCompleteEvent.bind(this));importer.registerEventHandler('regulator_disable',RegulatorParser.prototype.regulatorDisableEvent.bind(this));importer.registerEventHandler('regulator_disable_complete',RegulatorParser.prototype.regulatorDisableCompleteEvent.bind(this));importer.registerEventHandler('regulator_set_voltage',RegulatorParser.prototype.regulatorSetVoltageEvent.bind(this));importer.registerEventHandler('regulator_set_voltage_complete',RegulatorParser.prototype.regulatorSetVoltageCompleteEvent.bind(this));this.model_=importer.model_;}
-var regulatorEnableRE=/name=(.+)/;var regulatorDisableRE=/name=(.+)/;var regulatorSetVoltageCompleteRE=/name=(\S+), val=(\d+)/;RegulatorParser.prototype={__proto__:Parser.prototype,getCtr_:function(ctrName,valueName){var ctr=this.model_.kernel.getOrCreateCounter(null,'vreg '+ctrName+' '+valueName);if(ctr.series[0]===undefined){ctr.addSeries(new tv.c.trace_model.CounterSeries(valueName,tv.b.ui.getColorIdForGeneralPurposeString(ctrName+'.'+valueName)));}
+return false;var targetCpuNumber=parseInt(event[2]);var cpuState=parseInt(event[1]);this.cpuIdleSlice(ts,targetCpuNumber,cpuState);return true;}};Parser.register(PowerParser);return{PowerParser:PowerParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function RegulatorParser(importer){Parser.call(this,importer);importer.registerEventHandler('regulator_enable',RegulatorParser.prototype.regulatorEnableEvent.bind(this));importer.registerEventHandler('regulator_enable_delay',RegulatorParser.prototype.regulatorEnableDelayEvent.bind(this));importer.registerEventHandler('regulator_enable_complete',RegulatorParser.prototype.regulatorEnableCompleteEvent.bind(this));importer.registerEventHandler('regulator_disable',RegulatorParser.prototype.regulatorDisableEvent.bind(this));importer.registerEventHandler('regulator_disable_complete',RegulatorParser.prototype.regulatorDisableCompleteEvent.bind(this));importer.registerEventHandler('regulator_set_voltage',RegulatorParser.prototype.regulatorSetVoltageEvent.bind(this));importer.registerEventHandler('regulator_set_voltage_complete',RegulatorParser.prototype.regulatorSetVoltageCompleteEvent.bind(this));this.model_=importer.model_;}
+var regulatorEnableRE=/name=(.+)/;var regulatorDisableRE=/name=(.+)/;var regulatorSetVoltageCompleteRE=/name=(\S+), val=(\d+)/;RegulatorParser.prototype={__proto__:Parser.prototype,getCtr_:function(ctrName,valueName){var ctr=this.model_.kernel.getOrCreateCounter(null,'vreg '+ctrName+' '+valueName);if(ctr.series[0]===undefined){ctr.addSeries(new tr.model.CounterSeries(valueName,tr.b.ui.getColorIdForGeneralPurposeString(ctrName+'.'+valueName)));}
 return ctr;},regulatorEnableEvent:function(eventName,cpuNum,pid,ts,eventBase){var event=regulatorEnableRE.exec(eventBase.details);if(!event)
 return false;var name=event[1];var ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,1);return true;},regulatorEnableDelayEvent:function(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorEnableCompleteEvent:function(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorDisableEvent:function(eventName,cpuNum,pid,ts,eventBase){var event=regulatorDisableRE.exec(eventBase.details);if(!event)
 return false;var name=event[1];var ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,0);return true;},regulatorDisableCompleteEvent:function(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageEvent:function(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageCompleteEvent:function(eventName,cpuNum,pid,ts,eventBase){var event=regulatorSetVoltageCompleteRE.exec(eventBase.details);if(!event)
-return false;var name=event[1];var voltage=parseInt(event[2]);var ctr=this.getCtr_(name,'voltage');ctr.series[0].addCounterSample(ts,voltage);return true;}};Parser.register(RegulatorParser);return{RegulatorParser:RegulatorParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function SchedParser(importer){Parser.call(this,importer);importer.registerEventHandler('sched_switch',SchedParser.prototype.schedSwitchEvent.bind(this));importer.registerEventHandler('sched_wakeup',SchedParser.prototype.schedWakeupEvent.bind(this));}
+return false;var name=event[1];var voltage=parseInt(event[2]);var ctr=this.getCtr_(name,'voltage');ctr.series[0].addCounterSample(ts,voltage);return true;}};Parser.register(RegulatorParser);return{RegulatorParser:RegulatorParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function SchedParser(importer){Parser.call(this,importer);importer.registerEventHandler('sched_switch',SchedParser.prototype.schedSwitchEvent.bind(this));importer.registerEventHandler('sched_wakeup',SchedParser.prototype.schedWakeupEvent.bind(this));}
 var TestExports={};var schedSwitchRE=new RegExp('prev_comm=(.+) prev_pid=(\\d+) prev_prio=(\\d+) '+'prev_state=(\\S\\+?|\\S\\|\\S) ==> '+'next_comm=(.+) next_pid=(\\d+) next_prio=(\\d+)');TestExports.schedSwitchRE=schedSwitchRE;var schedWakeupRE=/comm=(.+) pid=(\d+) prio=(\d+) success=(\d+) target_cpu=(\d+)/;TestExports.schedWakeupRE=schedWakeupRE;SchedParser.prototype={__proto__:Parser.prototype,schedSwitchEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=schedSwitchRE.exec(eventBase.details);if(!event)
 return false;var prevState=event[4];var nextComm=event[5];var nextPid=parseInt(event[6]);var nextPrio=parseInt(event[7]);var nextThread=this.importer.threadsByLinuxPid[nextPid];var nextName;if(nextThread)
 nextName=nextThread.userFriendlyName;else
 nextName=nextComm;var cpu=this.importer.getOrCreateCpu(cpuNumber);cpu.switchActiveThread(ts,{stateWhenDescheduled:prevState},nextPid,nextName,{comm:nextComm,tid:nextPid,prio:nextPrio});return true;},schedWakeupEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=schedWakeupRE.exec(eventBase.details);if(!event)
-return false;var fromPid=pid;var comm=event[1];var pid=parseInt(event[2]);var prio=parseInt(event[3]);this.importer.markPidRunnable(ts,pid,comm,prio,fromPid);return true;}};Parser.register(SchedParser);return{SchedParser:SchedParser,_SchedParserTestExports:TestExports};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function SyncParser(importer){Parser.call(this,importer);importer.registerEventHandler('sync_timeline',SyncParser.prototype.timelineEvent.bind(this));importer.registerEventHandler('sync_wait',SyncParser.prototype.syncWaitEvent.bind(this));importer.registerEventHandler('sync_pt',SyncParser.prototype.syncPtEvent.bind(this));this.model_=importer.model_;}
+return false;var fromPid=pid;var comm=event[1];var pid=parseInt(event[2]);var prio=parseInt(event[3]);this.importer.markPidRunnable(ts,pid,comm,prio,fromPid);return true;}};Parser.register(SchedParser);return{SchedParser:SchedParser,_SchedParserTestExports:TestExports};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function SyncParser(importer){Parser.call(this,importer);importer.registerEventHandler('sync_timeline',SyncParser.prototype.timelineEvent.bind(this));importer.registerEventHandler('sync_wait',SyncParser.prototype.syncWaitEvent.bind(this));importer.registerEventHandler('sync_pt',SyncParser.prototype.syncPtEvent.bind(this));this.model_=importer.model_;}
 var syncTimelineRE=/name=(\S+) value=(\S*)/;var syncWaitRE=/(\S+) name=(\S+) state=(\d+)/;var syncPtRE=/name=(\S+) value=(\S*)/;SyncParser.prototype={__proto__:Parser.prototype,timelineEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=syncTimelineRE.exec(eventBase.details);if(!event)
 return false;var thread=this.importer.getOrCreatePseudoThread(event[1]);if(thread.lastActiveTs!==undefined){var duration=ts-thread.lastActiveTs;var value=thread.lastActiveValue;if(value==undefined)
-value=' ';var slice=new tv.c.trace_model.Slice('',value,tv.b.ui.getColorIdForGeneralPurposeString(value),thread.lastActiveTs,{},duration);thread.thread.sliceGroup.pushSlice(slice);}
+value=' ';var slice=new tr.model.Slice('',value,tr.b.ui.getColorIdForGeneralPurposeString(value),thread.lastActiveTs,{},duration);thread.thread.sliceGroup.pushSlice(slice);}
 thread.lastActiveTs=ts;thread.lastActiveValue=event[2];return true;},syncWaitEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=syncWaitRE.exec(eventBase.details);if(!event)
 return false;if(eventBase.tgid===undefined){return false;}
 var tgid=parseInt(eventBase.tgid);var thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;var slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
 var name='fence_wait("'+event[2]+'")';if(event[1]=='begin'){var slice=slices.beginSlice(null,name,ts,{'Start state':event[3]});}else if(event[1]=='end'){if(slices.openSliceCount>0){slices.endSlice(ts);}}else{return false;}
 return true;},syncPtEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=syncPtRE.exec(eventBase.details);if(!event)
-return false;return true;var thread=this.importer.getOrCreateKernelThread(eventBase[1]).thread;thread.syncWaitSyncPts[event[1]]=event[2];return true;}};Parser.register(SyncParser);return{SyncParser:SyncParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function WorkqueueParser(importer){Parser.call(this,importer);importer.registerEventHandler('workqueue_execute_start',WorkqueueParser.prototype.executeStartEvent.bind(this));importer.registerEventHandler('workqueue_execute_end',WorkqueueParser.prototype.executeEndEvent.bind(this));importer.registerEventHandler('workqueue_queue_work',WorkqueueParser.prototype.executeQueueWork.bind(this));importer.registerEventHandler('workqueue_activate_work',WorkqueueParser.prototype.executeActivateWork.bind(this));}
+return false;return true;var thread=this.importer.getOrCreateKernelThread(eventBase[1]).thread;thread.syncWaitSyncPts[event[1]]=event[2];return true;}};Parser.register(SyncParser);return{SyncParser:SyncParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function WorkqueueParser(importer){Parser.call(this,importer);importer.registerEventHandler('workqueue_execute_start',WorkqueueParser.prototype.executeStartEvent.bind(this));importer.registerEventHandler('workqueue_execute_end',WorkqueueParser.prototype.executeEndEvent.bind(this));importer.registerEventHandler('workqueue_queue_work',WorkqueueParser.prototype.executeQueueWork.bind(this));importer.registerEventHandler('workqueue_activate_work',WorkqueueParser.prototype.executeActivateWork.bind(this));}
 var workqueueExecuteStartRE=/work struct (.+): function (\S+)/;var workqueueExecuteEndRE=/work struct (.+)/;WorkqueueParser.prototype={__proto__:Parser.prototype,executeStartEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=workqueueExecuteStartRE.exec(eventBase.details);if(!event)
 return false;var kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);kthread.openSliceTS=ts;kthread.openSlice=event[2];return true;},executeEndEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=workqueueExecuteEndRE.exec(eventBase.details);if(!event)
-return false;var kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);if(kthread.openSlice){var slice=new tv.c.trace_model.Slice('',kthread.openSlice,tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,{},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
-kthread.openSlice=undefined;return true;},executeQueueWork:function(eventName,cpuNumber,pid,ts,eventBase){return true;},executeActivateWork:function(eventName,cpuNumber,pid,ts,eventBase){return true;}};Parser.register(WorkqueueParser);return{WorkqueueParser:WorkqueueParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Parser=tv.e.importer.linux_perf.Parser;function AndroidParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:android',AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));importer.registerEventHandler('0:android',AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+return false;var kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);if(kthread.openSlice){var slice=new tr.model.Slice('',kthread.openSlice,tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,{},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+kthread.openSlice=undefined;return true;},executeQueueWork:function(eventName,cpuNumber,pid,ts,eventBase){return true;},executeActivateWork:function(eventName,cpuNumber,pid,ts,eventBase){return true;}};Parser.register(WorkqueueParser);return{WorkqueueParser:WorkqueueParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Parser=tr.e.importer.linux_perf.Parser;function AndroidParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:android',AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));importer.registerEventHandler('0:android',AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
 function parseArgs(argsString){var args={};if(argsString){var argsArray=argsString.split(';');for(var i=0;i<argsArray.length;++i){var parts=argsArray[i].split('=');if(parts[0])
 args[parts.shift()]=parts.join('=');}}
 return args;}
-AndroidParser.prototype={__proto__:Parser.prototype,openAsyncSlice:function(thread,category,name,cookie,ts,args){var asyncSliceConstructor=tv.c.trace_model.AsyncSlice.getConstructor(category,name);var slice=new asyncSliceConstructor(category,name,tv.b.ui.getColorIdForGeneralPurposeString(name),ts,args);var key=category+':'+name+':'+cookie;slice.id=cookie;slice.startThread=thread;if(!this.openAsyncSlices){this.openAsyncSlices={};}
+AndroidParser.prototype={__proto__:Parser.prototype,openAsyncSlice:function(thread,category,name,cookie,ts,args){var asyncSliceConstructor=tr.model.AsyncSlice.getConstructor(category,name);var slice=new asyncSliceConstructor(category,name,tr.b.ui.getColorIdForGeneralPurposeString(name),ts,args);var key=category+':'+name+':'+cookie;slice.id=cookie;slice.startThread=thread;if(!this.openAsyncSlices){this.openAsyncSlices={};}
 this.openAsyncSlices[key]=slice;},closeAsyncSlice:function(thread,category,name,cookie,ts,args){if(!this.openAsyncSlices){return;}
 var key=category+':'+name+':'+cookie;var slice=this.openAsyncSlices[key];if(!slice){return;}
 for(var arg in args){if(slice.args[arg]!==undefined){this.model_.importWarning({type:'parse_error',message:'Both the S and F events of '+slice.title+' provided values for argument '+arg+'.'+' The value of the F event will be used.'});}
 slice.args[arg]=args[arg];}
-slice.endThread=thread;slice.duration=ts-slice.start;slice.startThread.asyncSliceGroup.push(slice);slice.subSlices=[new tv.c.trace_model.AsyncSlice(slice.category,slice.title,slice.colorId,slice.start,slice.args,slice.duration)];delete this.openAsyncSlices[key];},traceMarkWriteAndroidEvent:function(eventName,cpuNumber,pid,ts,eventBase){var eventData=eventBase.details.split('|');switch(eventData[0]){case'B':var ppid=parseInt(eventData[1]);var title=eventData[2];var args=parseArgs(eventData[3]);var category=eventData[4];if(category===undefined)
+slice.endThread=thread;slice.duration=ts-slice.start;slice.startThread.asyncSliceGroup.push(slice);slice.subSlices=[new tr.model.AsyncSlice(slice.category,slice.title,slice.colorId,slice.start,slice.args,slice.duration)];delete this.openAsyncSlices[key];},traceMarkWriteAndroidEvent:function(eventName,cpuNumber,pid,ts,eventBase){var eventData=eventBase.details.split('|');switch(eventData[0]){case'B':var ppid=parseInt(eventData[1]);var title=eventData[2];var args=parseArgs(eventData[3]);var category=eventData[4];if(category===undefined)
 category='android';var thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);thread.name=eventBase.threadName;if(!thread.sliceGroup.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
 this.ppids_[pid]=ppid;thread.sliceGroup.beginSlice(category,title,ts,args);break;case'E':var ppid=this.ppids_[pid];if(ppid===undefined){break;}
 var thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);if(!thread.sliceGroup.openSliceCount){break;}
 var slice=thread.sliceGroup.endSlice(ts);var args=parseArgs(eventData[3]);for(var arg in args){if(slice.args[arg]!==undefined){this.model_.importWarning({type:'parse_error',message:'Both the B and E events of '+slice.title+' provided values for argument '+arg+'.'+' The value of the E event will be used.'});}
 slice.args[arg]=args[arg];}
 break;case'C':var ppid=parseInt(eventData[1]);var name=eventData[2];var value=parseInt(eventData[3]);var category=eventData[4];if(category===undefined)
-category='android';var ctr=this.model_.getOrCreateProcess(ppid).getOrCreateCounter(category,name);if(ctr.numSeries===0){ctr.addSeries(new tv.c.trace_model.CounterSeries(value,tv.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+category='android';var ctr=this.model_.getOrCreateProcess(ppid).getOrCreateCounter(category,name);if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries(value,tr.b.ui.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
 ctr.series.forEach(function(series){series.addCounterSample(ts,value);});break;case'S':var ppid=parseInt(eventData[1]);var name=eventData[2];var cookie=parseInt(eventData[3]);var args=parseArgs(eventData[4]);var category=eventData[5];if(category===undefined)
 category='android';var thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);thread.name=eventBase.threadName;this.ppids_[pid]=ppid;this.openAsyncSlice(thread,category,name,cookie,ts,args);break;case'F':var ppid=parseInt(eventData[1]);var name=eventData[2];var cookie=parseInt(eventData[3]);var args=parseArgs(eventData[4]);var category=eventData[5];if(category===undefined)
 category='android';var thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);thread.name=eventBase.threadName;this.ppids_[pid]=ppid;this.closeAsyncSlice(thread,category,name,cookie,ts,args);break;default:return false;}
-return true;}};Parser.register(AndroidParser);return{AndroidParser:AndroidParser};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var LinuxPerfParser=tv.e.importer.linux_perf.Parser;function KernelFuncParser(importer){LinuxPerfParser.call(this,importer);importer.registerEventHandler('graph_ent',KernelFuncParser.prototype.traceKernelFuncEnterEvent.bind(this));importer.registerEventHandler('graph_ret',KernelFuncParser.prototype.traceKernelFuncReturnEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+return true;}};Parser.register(AndroidParser);return{AndroidParser:AndroidParser};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var LinuxPerfParser=tr.e.importer.linux_perf.Parser;function KernelFuncParser(importer){LinuxPerfParser.call(this,importer);importer.registerEventHandler('graph_ent',KernelFuncParser.prototype.traceKernelFuncEnterEvent.bind(this));importer.registerEventHandler('graph_ret',KernelFuncParser.prototype.traceKernelFuncReturnEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
 var TestExports={};var funcEnterRE=new RegExp('func=(.+)');TestExports.funcEnterRE=funcEnterRE;KernelFuncParser.prototype={__proto__:LinuxPerfParser.prototype,traceKernelFuncEnterEvent:function(eventName,cpuNumber,pid,ts,eventBase){var eventData=funcEnterRE.exec(eventBase.details);if(!eventData)
 return false;if(eventBase.tgid===undefined){return false;}
 var tgid=parseInt(eventBase.tgid);var name=eventData[1];var thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;var slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
 var slice=slices.beginSlice(null,name,ts,{});return true;},traceKernelFuncReturnEvent:function(eventName,cpuNumber,pid,ts,eventBase){if(eventBase.tgid===undefined){return false;}
 var tgid=parseInt(eventBase.tgid);var thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;var slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
 if(slices.openSliceCount>0){slices.endSlice(ts);}
-return true;}};LinuxPerfParser.register(KernelFuncParser);return{KernelFuncParser:KernelFuncParser};});'use strict';tv.exportTo('tv.c.importer',function(){function SimpleLineReader(text){this.lines_=text.split('\n');this.curLine_=0;this.savedLines_=undefined;}
+return true;}};LinuxPerfParser.register(KernelFuncParser);return{KernelFuncParser:KernelFuncParser};});'use strict';tr.exportTo('tr.importer',function(){function SimpleLineReader(text){this.lines_=text.split('\n');this.curLine_=0;this.savedLines_=undefined;}
 SimpleLineReader.prototype={advanceToLineMatching:function(regex){for(;this.curLine_<this.lines_.length;this.curLine_++){var line=this.lines_[this.curLine_];if(this.savedLines_!==undefined)
 this.savedLines_.push(line);if(regex.test(line))
 return true;}
-return false;},get curLineNumber(){return this.curLine_;},beginSavingLines:function(){this.savedLines_=[];},endSavingLinesAndGetResult:function(){var tmp=this.savedLines_;this.savedLines_=undefined;return tmp;}};return{SimpleLineReader:SimpleLineReader};});'use strict';tv.exportTo('tv.e.importer.linux_perf',function(){var Importer=tv.c.importer.Importer;var ClockSyncRecord=tv.c.ClockSyncRecord;function LinuxPerfImporter(model,events){this.importPriority=2;this.model_=model;this.events_=events;this.newlyAddedClockSyncRecords_=[];this.wakeups_=[];this.kernelThreadStates_={};this.buildMapFromLinuxPidsToThreads();this.lines_=[];this.pseudoThreadCounter=1;this.parsers_=[];this.eventHandlers_={};}
+return false;},get curLineNumber(){return this.curLine_;},beginSavingLines:function(){this.savedLines_=[];},endSavingLinesAndGetResult:function(){var tmp=this.savedLines_;this.savedLines_=undefined;return tmp;}};return{SimpleLineReader:SimpleLineReader};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){var Importer=tr.importer.Importer;var ClockSyncRecord=tr.ClockSyncRecord;function LinuxPerfImporter(model,events){this.importPriority=2;this.model_=model;this.events_=events;this.newlyAddedClockSyncRecords_=[];this.wakeups_=[];this.kernelThreadStates_={};this.buildMapFromLinuxPidsToThreads();this.lines_=[];this.pseudoThreadCounter=1;this.parsers_=[];this.eventHandlers_={};}
 var TestExports={};var lineREWithTGID=new RegExp('^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]'+'\\s+[dX.][N.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');var lineParserWithTGID=function(line){var groups=lineREWithTGID.exec(line);if(!groups){return groups;}
 var tgid=groups[3];if(tgid[0]==='-')
 tgid=undefined;return{threadName:groups[1],pid:groups[2],tgid:tgid,cpuNumber:groups[4],timestamp:groups[5],eventName:groups[6],details:groups[7]};};TestExports.lineParserWithTGID=lineParserWithTGID;var lineREWithIRQInfo=new RegExp('^\\s*(.+)-(\\d+)\\s+\\[(\\d+)\\]'+'\\s+[dX.][N.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');var lineParserWithIRQInfo=function(line){var groups=lineREWithIRQInfo.exec(line);if(!groups){return groups;}
@@ -3891,7 +3965,7 @@
 events=events.substring(0,lineBreakIndex);if(autoDetectLineParser(events))
 return true;return false;};LinuxPerfImporter._extractEventsFromSystraceHTML=function(incoming_events,produce_result){var failure={ok:false};if(produce_result===undefined)
 produce_result=true;if(/^<!DOCTYPE HTML>/.test(incoming_events)==false)
-return failure;var r=new tv.c.importer.SimpleLineReader(incoming_events);if(!r.advanceToLineMatching(/^  <script>$/))
+return failure;var r=new tr.importer.SimpleLineReader(incoming_events);if(!r.advanceToLineMatching(/^  <script>$/))
 return failure;if(!r.advanceToLineMatching(/^  var linuxPerfData = "\\$/))
 return failure;var events_begin_at_line=r.curLineNumber+1;r.beginSavingLines();if(!r.advanceToLineMatching(/^  <\/script>$/))
 return failure;var raw_events=r.endSavingLinesAndGetResult();raw_events=raw_events.slice(1,raw_events.length-1);if(!r.advanceToLineMatching(/^<\/body>$/))
@@ -3903,7 +3977,7 @@
 var oldLastEvent=events[events.length-1];var newLastEvent=stripSuffix(oldLastEvent,'\\n";');if(newLastEvent==oldLastEvent)
 return failure;events[events.length-1]=newLastEvent;return{ok:true,lines:produce_result?events:undefined,events_begin_at_line:events_begin_at_line};};LinuxPerfImporter._extractEventsFromSystraceMultiHTML=function(incoming_events,produce_result){var failure={ok:false};if(produce_result===undefined)
 produce_result=true;if(/^<!DOCTYPE HTML>/.test(incoming_events)==false)
-return failure;var r=new tv.c.importer.SimpleLineReader(incoming_events);var events=[];while(!/^# tracer:/.test(events)){if(!r.advanceToLineMatching(/^  <script class="trace-data" type="application\/text">$/))
+return failure;var r=new tr.importer.SimpleLineReader(incoming_events);var events=[];while(!/^# tracer:/.test(events)){if(!r.advanceToLineMatching(/^  <script class="trace-data" type="application\/text">$/))
 return failure;var events_begin_at_line=r.curLineNumber+1;r.beginSavingLines();if(!r.advanceToLineMatching(/^  <\/script>$/))
 return failure;events=r.endSavingLinesAndGetResult();events=events.slice(1,events.length-1);}
 if(!r.advanceToLineMatching(/^<\/body>$/))
@@ -3911,22 +3985,22 @@
 return failure;return{ok:true,lines:produce_result?events:undefined,events_begin_at_line:events_begin_at_line};};LinuxPerfImporter.prototype={__proto__:Importer.prototype,get model(){return this.model_;},buildMapFromLinuxPidsToThreads:function(){this.threadsByLinuxPid={};this.model_.getAllThreads().forEach(function(thread){this.threadsByLinuxPid[thread.tid]=thread;}.bind(this));},getOrCreateCpu:function(cpuNumber){return this.model_.kernel.getOrCreateCpu(cpuNumber);},getOrCreateKernelThread:function(kernelThreadName,pid,tid){if(!this.kernelThreadStates_[kernelThreadName]){var thread=this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);thread.name=kernelThreadName;this.kernelThreadStates_[kernelThreadName]={pid:pid,thread:thread,openSlice:undefined,openSliceTS:undefined};this.threadsByLinuxPid[pid]=thread;}
 return this.kernelThreadStates_[kernelThreadName];},getOrCreatePseudoThread:function(threadName){var thread=this.kernelThreadStates_[threadName];if(!thread){thread=this.getOrCreateKernelThread(threadName,pseudoKernelPID,this.pseudoThreadCounter);this.pseudoThreadCounter++;}
 return thread;},importEvents:function(isSecondaryImport){this.parsers_=this.createParsers_();this.registerDefaultHandlers_();this.parseLines();this.importClockSyncRecords();var timeShift=this.computeTimeTransform();if(timeShift===undefined){this.model_.importWarning({type:'clock_sync',message:'Cannot import kernel trace without a clock sync.'});return;}
-this.shiftNewlyAddedClockSyncRecords(timeShift);this.importCpuData(timeShift);this.buildMapFromLinuxPidsToThreads();this.buildPerThreadCpuSlicesFromCpuState();this.computeCpuTimestampsForSlicesAsNeeded();},buildPerThreadCpuSlicesFromCpuState:function(){var SCHEDULING_STATE=tv.c.trace_model.SCHEDULING_STATE;for(var cpuNumber in this.model_.kernel.cpus){var cpu=this.model_.kernel.cpus[cpuNumber];for(var i=0;i<cpu.slices.length;i++){var cpuSlice=cpu.slices[i];var thread=this.threadsByLinuxPid[cpuSlice.args.tid];if(!thread)
+this.shiftNewlyAddedClockSyncRecords(timeShift);this.importCpuData(timeShift);this.buildMapFromLinuxPidsToThreads();this.buildPerThreadCpuSlicesFromCpuState();this.computeCpuTimestampsForSlicesAsNeeded();},buildPerThreadCpuSlicesFromCpuState:function(){var SCHEDULING_STATE=tr.model.SCHEDULING_STATE;for(var cpuNumber in this.model_.kernel.cpus){var cpu=this.model_.kernel.cpus[cpuNumber];for(var i=0;i<cpu.slices.length;i++){var cpuSlice=cpu.slices[i];var thread=this.threadsByLinuxPid[cpuSlice.args.tid];if(!thread)
 continue;cpuSlice.threadThatWasRunning=thread;if(!thread.tempCpuSlices)
 thread.tempCpuSlices=[];thread.tempCpuSlices.push(cpuSlice);}}
 for(var i in this.wakeups_){var wakeup=this.wakeups_[i];var thread=this.threadsByLinuxPid[wakeup.tid];if(!thread)
 continue;thread.tempWakeups=thread.tempWakeups||[];thread.tempWakeups.push(wakeup);}
 this.model_.getAllThreads().forEach(function(thread){if(thread.tempCpuSlices===undefined)
-return;var origSlices=thread.tempCpuSlices;delete thread.tempCpuSlices;origSlices.sort(function(x,y){return x.start-y.start;});var wakeups=thread.tempWakeups||[];delete thread.tempWakeups;wakeups.sort(function(x,y){return x.ts-y.ts;});var slices=[];if(origSlices.length){var slice=origSlices[0];if(wakeups.length&&wakeups[0].ts<slice.start){var wakeup=wakeups.shift();var wakeupDuration=slice.start-wakeup.ts;var args={'wakeup from tid':wakeup.fromTid};slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',wakeup.ts,args,wakeupDuration));}
-var runningSlice=new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNING,'',slice.start,{},slice.duration);runningSlice.cpuOnWhichThreadWasRunning=slice.cpu;slices.push(runningSlice);}
+return;var origSlices=thread.tempCpuSlices;delete thread.tempCpuSlices;origSlices.sort(function(x,y){return x.start-y.start;});var wakeups=thread.tempWakeups||[];delete thread.tempWakeups;wakeups.sort(function(x,y){return x.ts-y.ts;});var slices=[];if(origSlices.length){var slice=origSlices[0];if(wakeups.length&&wakeups[0].ts<slice.start){var wakeup=wakeups.shift();var wakeupDuration=slice.start-wakeup.ts;var args={'wakeup from tid':wakeup.fromTid};slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',wakeup.ts,args,wakeupDuration));}
+var runningSlice=new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNING,'',slice.start,{},slice.duration);runningSlice.cpuOnWhichThreadWasRunning=slice.cpu;slices.push(runningSlice);}
 var wakeup=undefined;for(var i=1;i<origSlices.length;i++){var prevSlice=origSlices[i-1];var nextSlice=origSlices[i];var midDuration=nextSlice.start-prevSlice.end;while(wakeups.length&&wakeups[0].ts<nextSlice.start){var w=wakeups.shift();if(wakeup===undefined&&w.ts>prevSlice.end){wakeup=w;}}
 var pushSleep=function(state){if(wakeup!==undefined){midDuration=wakeup.ts-prevSlice.end;}
-slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,state,'',prevSlice.end,{},midDuration));if(wakeup!==undefined){var wakeupDuration=nextSlice.start-wakeup.ts;var args={'wakeup from tid':wakeup.fromTid};slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',wakeup.ts,args,wakeupDuration));wakeup=undefined;}};if(prevSlice.args.stateWhenDescheduled=='S'){pushSleep(SCHEDULING_STATE.SLEEPING);}else if(prevSlice.args.stateWhenDescheduled=='R'||prevSlice.args.stateWhenDescheduled=='R+'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='D'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP);}else if(prevSlice.args.stateWhenDescheduled=='T'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.STOPPED,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='t'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.DEBUG,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='Z'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.ZOMBIE,'',ioWaitId,prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='X'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.EXIT_DEAD,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='x'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.TASK_DEAD,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='K'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.WAKE_KILL,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='W'){slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.WAKING,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='D|K'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL);}else if(prevSlice.args.stateWhenDescheduled=='D|W'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKING);}else{slices.push(new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.UNKNOWN,'',prevSlice.end,{},midDuration));this.model_.importWarning({type:'parse_error',message:'Unrecognized sleep state: '+
+slices.push(new tr.model.ThreadTimeSlice(thread,state,'',prevSlice.end,{},midDuration));if(wakeup!==undefined){var wakeupDuration=nextSlice.start-wakeup.ts;var args={'wakeup from tid':wakeup.fromTid};slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',wakeup.ts,args,wakeupDuration));wakeup=undefined;}};if(prevSlice.args.stateWhenDescheduled=='S'){pushSleep(SCHEDULING_STATE.SLEEPING);}else if(prevSlice.args.stateWhenDescheduled=='R'||prevSlice.args.stateWhenDescheduled=='R+'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='D'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP);}else if(prevSlice.args.stateWhenDescheduled=='T'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.STOPPED,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='t'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.DEBUG,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='Z'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.ZOMBIE,'',ioWaitId,prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='X'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.EXIT_DEAD,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='x'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.TASK_DEAD,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='K'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.WAKE_KILL,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='W'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.WAKING,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled=='D|K'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL);}else if(prevSlice.args.stateWhenDescheduled=='D|W'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKING);}else{slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.UNKNOWN,'',prevSlice.end,{},midDuration));this.model_.importWarning({type:'parse_error',message:'Unrecognized sleep state: '+
 prevSlice.args.stateWhenDescheduled});}
-var runningSlice=new tv.c.trace_model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNING,'',nextSlice.start,{},nextSlice.duration);runningSlice.cpuOnWhichThreadWasRunning=prevSlice.cpu;slices.push(runningSlice);}
+var runningSlice=new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNING,'',nextSlice.start,{},nextSlice.duration);runningSlice.cpuOnWhichThreadWasRunning=prevSlice.cpu;slices.push(runningSlice);}
 thread.timeSlices=slices;},this);},computeCpuTimestampsForSlicesAsNeeded:function(){},computeTimeTransform:function(){var isSecondaryImport=this.model.getClockSyncRecordsNamed('ftrace_importer').length!==0;var mSyncs=this.model_.getClockSyncRecordsNamed('monotonic');if(mSyncs.length==0)
 return isSecondaryImport?undefined:0;var sync=mSyncs[0].args;if(sync.parentTS==0||sync.parentTS==sync.perfTS)
-return 0;return sync.parentTS-sync.perfTS;},createParsers_:function(){var allTypeInfos=tv.e.importer.linux_perf.Parser.getAllRegisteredTypeInfos();var parsers=allTypeInfos.map(function(typeInfo){return new typeInfo.constructor(this);},this);return parsers;},registerDefaultHandlers_:function(){this.registerEventHandler('tracing_mark_write',LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));this.registerEventHandler('0',LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));this.registerEventHandler('tracing_mark_write:trace_event_clock_sync',function(){return true;});this.registerEventHandler('0:trace_event_clock_sync',function(){return true;});},registerEventHandler:function(eventName,handler){this.eventHandlers_[eventName]=handler;},markPidRunnable:function(ts,pid,comm,prio,fromPid){this.wakeups_.push({ts:ts,tid:pid,fromTid:fromPid});},traceClockSyncEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/name=(\w+?)\s(.+)/.exec(eventBase.details);if(event){var name=event[1];var pieces=event[2].split(' ');var args={perfTS:ts};for(var i=0;i<pieces.length;i++){var parts=pieces[i].split('=');if(parts.length!=2)
+return 0;return sync.parentTS-sync.perfTS;},createParsers_:function(){var allTypeInfos=tr.e.importer.linux_perf.Parser.getAllRegisteredTypeInfos();var parsers=allTypeInfos.map(function(typeInfo){return new typeInfo.constructor(this);},this);return parsers;},registerDefaultHandlers_:function(){this.registerEventHandler('tracing_mark_write',LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));this.registerEventHandler('0',LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));this.registerEventHandler('tracing_mark_write:trace_event_clock_sync',function(){return true;});this.registerEventHandler('0:trace_event_clock_sync',function(){return true;});},registerEventHandler:function(eventName,handler){this.eventHandlers_[eventName]=handler;},markPidRunnable:function(ts,pid,comm,prio,fromPid){this.wakeups_.push({ts:ts,tid:pid,fromTid:fromPid});},traceClockSyncEvent:function(eventName,cpuNumber,pid,ts,eventBase){var event=/name=(\w+?)\s(.+)/.exec(eventBase.details);if(event){var name=event[1];var pieces=event[2].split(' ');var args={perfTS:ts};for(var i=0;i<pieces.length;i++){var parts=pieces[i].split('=');if(parts.length!=2)
 throw new Error('omgbbq');args[parts[0]]=parts[1];}
 this.addClockSyncRecord(new ClockSyncRecord(name,ts,args));return true;}
 event=/parent_ts=(\d+\.?\d*)/.exec(eventBase.details);if(!event)
@@ -3940,7 +4014,7 @@
 extractResult=LinuxPerfImporter._extractEventsFromSystraceMultiHTML(this.events_,true);var lines=extractResult.ok?extractResult.lines:this.events_.split('\n');var lineParser=null;for(var lineNumber=0;lineNumber<lines.length;++lineNumber){var line=lines[lineNumber];if(line.length==0||/^#/.test(line))
 continue;if(lineParser==null){lineParser=autoDetectLineParser(line);if(lineParser==null){this.model_.importWarning({type:'parse_error',message:'Cannot parse line: '+line});continue;}}
 var eventBase=lineParser(line);if(!eventBase){this.model_.importWarning({type:'parse_error',message:'Unrecognized line: '+line});continue;}
-this.lines_.push([line,eventBase,parseInt(eventBase.cpuNumber),parseInt(eventBase.pid),parseFloat(eventBase.timestamp)*1000]);}},forEachLine:function(handler){for(var i=0;i<this.lines_.length;++i){var line=this.lines_[i];handler.apply(this,line);}}};tv.c.importer.Importer.register(LinuxPerfImporter);return{LinuxPerfImporter:LinuxPerfImporter,_LinuxPerfImporterTestExports:TestExports};});'use strict';tv.exportTo('tv.e.audits',function(){var MAIN_FRAMETIME_TYPE='main_frametime_type';var IMPL_FRAMETIME_TYPE='impl_frametime_type';var MAIN_RENDERING_STATS='BenchmarkInstrumentation::MainThreadRenderingStats';var IMPL_RENDERING_STATS='BenchmarkInstrumentation::ImplThreadRenderingStats';function getSlicesIntersectingRange(rangeOfInterest,slices){var slicesInFilterRange=[];for(var i=0;i<slices.length;i++){var slice=slices[i];if(rangeOfInterest.intersectsExplicitRange(slice.start,slice.end))
+this.lines_.push([line,eventBase,parseInt(eventBase.cpuNumber),parseInt(eventBase.pid),parseFloat(eventBase.timestamp)*1000]);}},forEachLine:function(handler){for(var i=0;i<this.lines_.length;++i){var line=this.lines_[i];handler.apply(this,line);}}};tr.importer.Importer.register(LinuxPerfImporter);return{LinuxPerfImporter:LinuxPerfImporter,_LinuxPerfImporterTestExports:TestExports};});'use strict';tr.exportTo('tr.e.audits',function(){var MAIN_FRAMETIME_TYPE='main_frametime_type';var IMPL_FRAMETIME_TYPE='impl_frametime_type';var MAIN_RENDERING_STATS='BenchmarkInstrumentation::MainThreadRenderingStats';var IMPL_RENDERING_STATS='BenchmarkInstrumentation::ImplThreadRenderingStats';function getSlicesIntersectingRange(rangeOfInterest,slices){var slicesInFilterRange=[];for(var i=0;i<slices.length;i++){var slice=slices[i];if(rangeOfInterest.intersectsExplicitRange(slice.start,slice.end))
 slicesInFilterRange.push(slice);}
 return slicesInFilterRange;}
 function ChromeProcessHelper(modelHelper,process){this.modelHelper=modelHelper;this.process=process;}
@@ -3950,37 +4024,39 @@
 return;if(range.intersectsExplicitRange(event.start,event.end))
 frameEvents.push(event);});frameEvents.sort(function(a,b){return a.start-b.start});return frameEvents;}};function getFrametimeDataFromEvents(frameEvents){var frametimeData=[];for(var i=1;i<frameEvents.length;i++){var diff=frameEvents[i].start-frameEvents[i-1].start;frametimeData.push({'x':frameEvents[i].start,'frametime':diff});}
 return frametimeData;}
-return{ChromeProcessHelper:ChromeProcessHelper,MAIN_FRAMETIME_TYPE:MAIN_FRAMETIME_TYPE,IMPL_FRAMETIME_TYPE:IMPL_FRAMETIME_TYPE,MAIN_RENDERING_STATS:MAIN_RENDERING_STATS,IMPL_RENDERING_STATS:IMPL_RENDERING_STATS,getSlicesIntersectingRange:getSlicesIntersectingRange,getFrametimeDataFromEvents:getFrametimeDataFromEvents};});'use strict';tv.exportTo('tv.e.cc',function(){var AsyncSlice=tv.c.trace_model.AsyncSlice;var UI_COMP_NAME='INPUT_EVENT_LATENCY_UI_COMPONENT';var ORIGINAL_COMP_NAME='INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT';var BEGIN_COMP_NAME='INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT';var END_COMP_NAME='INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT';function InputLatencyAsyncSlice(){AsyncSlice.apply(this,arguments);}
-InputLatencyAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get inputLatency(){if(!('data'in this.args))
+return{ChromeProcessHelper:ChromeProcessHelper,MAIN_FRAMETIME_TYPE:MAIN_FRAMETIME_TYPE,IMPL_FRAMETIME_TYPE:IMPL_FRAMETIME_TYPE,MAIN_RENDERING_STATS:MAIN_RENDERING_STATS,IMPL_RENDERING_STATS:IMPL_RENDERING_STATS,getSlicesIntersectingRange:getSlicesIntersectingRange,getFrametimeDataFromEvents:getFrametimeDataFromEvents};});'use strict';tr.exportTo('tr.e.cc',function(){var AsyncSlice=tr.model.AsyncSlice;var UI_COMP_NAME='INPUT_EVENT_LATENCY_UI_COMPONENT';var ORIGINAL_COMP_NAME='INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT';var BEGIN_COMP_NAME='INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT';var END_COMP_NAME='INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT';function InputLatencyAsyncSlice(){AsyncSlice.apply(this,arguments);this.associatedEvents_=undefined;}
+InputLatencyAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get associatedEvents(){if(this.associatedEvents_!==undefined)
+return this.associatedEvents_;this.associatedEvents_=[];var modelIndices=this.startThread.parent.model.modelIndices;var matchedFlowEvents=modelIndices.getFlowEventsWithId(this.id);var eventGUIDs={};matchedFlowEvents.forEach(function(flowEvent){this.associatedEvents_.push(flowEvent);if(flowEvent.startSlice&&!eventGUIDs[flowEvent.startSlice.guid]){this.associatedEvents_.push(flowEvent.startSlice);eventGUIDs[flowEvent.startSlice.guid]=1;}
+if(flowEvent.startSlice&&!eventGUIDs[flowEvent.endSlice.guid]){this.associatedEvents_.push(flowEvent.endSlice);eventGUIDs[flowEvent.endSlice.guid]=1;}},this);return this.associatedEvents_;},get inputLatency(){if(!('data'in this.args))
 return undefined;var data=this.args.data;if(!(END_COMP_NAME in data))
 return undefined;var latency=0;var endTime=data[END_COMP_NAME].time;if(ORIGINAL_COMP_NAME in data){latency=endTime-data[ORIGINAL_COMP_NAME].time;}else if(UI_COMP_NAME in data){latency=endTime-data[UI_COMP_NAME].time;}else if(BEGIN_COMP_NAME in data){latency=endTime-data[BEGIN_COMP_NAME].time;}else{throw new Error('No valid begin latency component');}
-return latency;}};var eventTypeNames=['Char','GestureFlingCancel','GestureFlingStart','GestureScrollBegin','GestureScrollEnd','GestureScrollUpdate','GestureShowPress','GestureTap','GestureTapCancel','GestureTapDown','KeyUp','MouseDown','MouseMove','MouseUp','MouseWheel','RawKeyDown','ScrollUpdate','TouchEnd','TouchMove','TouchStart'];var allTypeNames=['InputLatency'];eventTypeNames.forEach(function(eventTypeName){allTypeNames.push('InputLatency:'+eventTypeName);allTypeNames.push('InputLatency::'+eventTypeName);});AsyncSlice.register(InputLatencyAsyncSlice,{typeNames:allTypeNames,categoryParts:['latencyInfo']});return{InputLatencyAsyncSlice:InputLatencyAsyncSlice};});'use strict';tv.exportTo('tv.e.audits',function(){function ChromeBrowserHelper(modelHelper,process){tv.e.audits.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrBrowserMain');}
+return latency;}};var eventTypeNames=['Char','GestureFlingCancel','GestureFlingStart','GestureScrollBegin','GestureScrollEnd','GestureScrollUpdate','GestureShowPress','GestureTap','GestureTapCancel','GestureTapDown','KeyUp','MouseDown','MouseMove','MouseUp','MouseWheel','RawKeyDown','ScrollUpdate','TouchEnd','TouchMove','TouchStart'];var allTypeNames=['InputLatency'];eventTypeNames.forEach(function(eventTypeName){allTypeNames.push('InputLatency:'+eventTypeName);allTypeNames.push('InputLatency::'+eventTypeName);});AsyncSlice.register(InputLatencyAsyncSlice,{typeNames:allTypeNames,categoryParts:['latencyInfo']});return{InputLatencyAsyncSlice:InputLatencyAsyncSlice};});'use strict';tr.exportTo('tr.e.audits',function(){function ChromeBrowserHelper(modelHelper,process){tr.e.audits.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrBrowserMain');}
 ChromeBrowserHelper.isBrowserProcess=function(process){if(!process.findAtMostOneThreadNamed('CrBrowserMain'))
-return false;return true;};ChromeBrowserHelper.prototype={__proto__:tv.e.audits.ChromeProcessHelper.prototype,get rendererProcesses(){return this.modelHelper.rendererProcesses;},getLoadingEventsInRange:function(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return slice.title.indexOf('WebContentsImpl Loading')===0&&rangeOfInterest.intersectsExplicitRange(slice.start,slice.end);});},getCommitProvisionalLoadEventsInRange:function(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return slice.title==='RenderFrameImpl::didCommitProvisionalLoad'&&rangeOfInterest.intersectsExplicitRange(slice.start,slice.end);});},get hasLatencyEvents(){var hasLatency=false;this.modelHelper.model.getAllThreads().some(function(thread){thread.iterateAllEvents(function(event){if(!event.isTopLevel)
-return;if(!(event instanceof tv.e.cc.InputLatencyAsyncSlice))
+return false;return true;};ChromeBrowserHelper.prototype={__proto__:tr.e.audits.ChromeProcessHelper.prototype,get rendererHelpers(){return this.modelHelper.rendererHelpers;},getLoadingEventsInRange:function(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return slice.title.indexOf('WebContentsImpl Loading')===0&&rangeOfInterest.intersectsExplicitRange(slice.start,slice.end);});},getCommitProvisionalLoadEventsInRange:function(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return slice.title==='RenderFrameImpl::didCommitProvisionalLoad'&&rangeOfInterest.intersectsExplicitRange(slice.start,slice.end);});},get hasLatencyEvents(){var hasLatency=false;this.modelHelper.model.getAllThreads().some(function(thread){thread.iterateAllEvents(function(event){if(!event.isTopLevel)
+return;if(!(event instanceof tr.e.cc.InputLatencyAsyncSlice))
 return;hasLatency=true;});return hasLatency;});return hasLatency;},getLatencyEventsInRange:function(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return(slice.title.indexOf('InputLatency')===0)&&rangeOfInterest.intersectsExplicitRange(slice.start,slice.end);});return latencyEvents;},getAllAsyncSlicesMatching:function(pred,opt_this){var events=[];this.iterAllThreads(function(thread){thread.iterateAllEvents(function(slice){if(pred.call(opt_this,slice))
 events.push(slice);});});return events;},getAllNetworkEventsInRange:function(rangeOfInterest){var networkEvents=[];this.modelHelper.model.getAllThreads().forEach(function(thread){thread.asyncSliceGroup.slices.forEach(function(slice){var match=false;if(slice.cat=='net'||slice.cat=='disabled-by-default-netlog'||slice.cat=='netlog'){match=true;}
 if(!match)
 return;if(rangeOfInterest.intersectsExplicitRange(slice.start,slice.end))
-networkEvents.push(slice);});});return networkEvents;},iterAllThreads:function(func,opt_this){tv.b.iterItems(this.process.threads,function(tid,thread){func.call(opt_this,thread);});this.rendererProcesses.forEach(function(rendererProcess){tv.b.iterItems(rendererProcess.threads,function(tid,thread){func.call(opt_this,thread);});});}};return{ChromeBrowserHelper:ChromeBrowserHelper};});'use strict';tv.exportTo('tv.e.audits',function(){function ChromeRendererHelper(modelHelper,process){tv.e.audits.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)
+networkEvents.push(slice);});});return networkEvents;},iterAllThreads:function(func,opt_this){tr.b.iterItems(this.process.threads,function(tid,thread){func.call(opt_this,thread);});tr.b.iterItems(this.rendererHelpers,function(pid,rendererHelper){var rendererProcess=rendererHelper.process;tr.b.iterItems(rendererProcess.threads,function(tid,thread){func.call(opt_this,thread);});},this);}};return{ChromeBrowserHelper:ChromeBrowserHelper};});'use strict';tr.exportTo('tr.e.audits',function(){function ChromeRendererHelper(modelHelper,process){tr.e.audits.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)
 return false;if(t.name.indexOf('CompositorTileWorker')===0)
 return true;if(t.name.indexOf('CompositorRasterWorker')===0)
 return true;return false;});};ChromeRendererHelper.isRenderProcess=function(process){if(!process.findAtMostOneThreadNamed('CrRendererMain'))
 return false;if(!process.findAtMostOneThreadNamed('Compositor'))
-return false;return true;};ChromeRendererHelper.prototype={__proto__:tv.e.audits.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;}};return{ChromeRendererHelper:ChromeRendererHelper};});'use strict';tv.exportTo('tv.e.audits',function(){function findChromeBrowserProcess(model){var browserProcesses=[];model.getAllProcesses().forEach(function(process){if(!tv.e.audits.ChromeBrowserHelper.isBrowserProcess(process))
+return false;return true;};ChromeRendererHelper.prototype={__proto__:tr.e.audits.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;}};return{ChromeRendererHelper:ChromeRendererHelper};});'use strict';tr.exportTo('tr.e.audits',function(){function findChromeBrowserProcess(model){var browserProcesses=[];model.getAllProcesses().forEach(function(process){if(!tr.e.audits.ChromeBrowserHelper.isBrowserProcess(process))
 return;browserProcesses.push(process);},this);if(browserProcesses.length===0)
 return undefined;if(browserProcesses.length>1)
 return undefined;return browserProcesses[0];}
-function findChromeRenderProcesses(model){var rendererProcesses=[];model.getAllProcesses().forEach(function(process){if(!tv.e.audits.ChromeRendererHelper.isRenderProcess(process))
+function findChromeRenderProcesses(model){var rendererProcesses=[];model.getAllProcesses().forEach(function(process){if(!tr.e.audits.ChromeRendererHelper.isRenderProcess(process))
 return;rendererProcesses.push(process);});return rendererProcesses;}
-function ChromeModelHelper(model){this.model_=model;this.browserProcess_=findChromeBrowserProcess(model);if(this.browserProcess_){this.browser_=new tv.e.audits.ChromeBrowserHelper(this,this.browserProcess_);}else{this.browser_=undefined;}
-this.rendererProcesses_=findChromeRenderProcesses(model);this.renderers_={};this.rendererProcesses_.forEach(function(renderProcess){var renderer=new tv.e.audits.ChromeRendererHelper(this,renderProcess);this.renderers_[renderer.pid]=renderer;},this);}
+function ChromeModelHelper(model){this.model_=model;this.browserProcess_=findChromeBrowserProcess(model);if(this.browserProcess_){this.browserHelper_=new tr.e.audits.ChromeBrowserHelper(this,this.browserProcess_);}else{this.browserHelper_=undefined;}
+var rendererProcesses_=findChromeRenderProcesses(model);this.rendererHelpers_={};rendererProcesses_.forEach(function(renderProcess){var rendererHelper=new tr.e.audits.ChromeRendererHelper(this,renderProcess);this.rendererHelpers_[rendererHelper.pid]=rendererHelper;},this);}
 ChromeModelHelper.supportsModel=function(model){if(findChromeBrowserProcess(model)!==undefined)
 return true;if(findChromeRenderProcesses(model).length)
 return true;return false;}
-ChromeModelHelper.prototype={get pid(){throw new Error('woah');},get process(){throw new Error('woah');},get model(){return this.model_;},get browserProcess(){return this.browserProcess_;},get browser(){return this.browser_;},get rendererProcesses(){return this.rendererProcesses_;},get renderers(){return this.renderers_;}};return{ChromeModelHelper:ChromeModelHelper};});!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function d(){Xo.event.preventDefault()}function m(){for(var n,t=Xo.event;n=t.sourceEvent;)t=n;return t}function y(n){for(var t=new p,e=0,r=arguments.length;++e<r;)t[arguments[e]]=v(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Xo.event;u.target=n,Xo.event=u,t[u.type].apply(e,r)}finally{Xo.event=i}}},t}function x(n){return fa(n,da),n}function M(n){return"function"==typeof n?n:function(){return ha(n,this)}}function _(n){return"function"==typeof n?n:function(){return ga(n,this)}}function b(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Xo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function w(n){return n.trim().replace(/\s+/g," ")}function S(n){return new RegExp("(?:^|\\s+)"+Xo.requote(n)+"(?:\\s+|$)","g")}function k(n){return n.trim().split(/^|\s+/)}function E(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=k(n).map(A);var u=n.length;return"function"==typeof t?r:e}function A(n){var t=S(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",w(u+" "+n))):e.setAttribute("class",w(u.replace(t," ")))}}function C(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function N(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function L(n){return"function"==typeof n?n:(n=Xo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function T(n){return{__data__:n}}function q(n){return function(){return va(this,n)}}function z(n){return arguments.length||(n=Xo.ascending),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function R(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function U(){var n=this.__transition__;n&&++n.active}function j(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Bo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Xo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=H;a>0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o,a=0,c=0,s=0;if(u=/([a-z]+)\((.*)\)/i.exec(n))switch(i=u[2].split(","),u[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Mt(i[0]),Mt(i[1]),Mt(i[2]))}return(o=Va.get(n))?t(o.r,o.g,o.b):(null!=n&&"#"===n.charAt(0)&&(r=parseInt(n.substring(1),16),isNaN(r)||(4===n.length?(a=(3840&r)>>4,a=a>>4|a,c=240&r,c=c>>4|c,s=15&r,s=s<<4|s):7===n.length&&(a=(16711680&r)>>16,c=(65280&r)>>8,s=255&r))),t(a,c,s))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return $a=n,e}function Nt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*oa(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Xo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function zt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=zt;var r=new zt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=zt;var r=new zt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=uc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&ec!==zt,o=new(i?zt:ec);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=zt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=zt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ft(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ot(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Yt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function It(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Zt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.y=Xt(+r[0]),e+r[0].length):-1}function Vt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Xt(n){return n+(n>68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function re(){}function ue(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function ie(n,t){n&&lc.hasOwnProperty(n.type)&&lc[n.type](n,t)}function oe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ae(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)oe(n[e],t,1);t.polygonEnd()}function ce(){function n(n,t){n*=Na,t=t*Na/2+Sa/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);hc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;gc.point=function(o,a){gc.point=n,r=(t=o)*Na,u=Math.cos(a=(e=a)*Na/2+Sa/4),i=Math.sin(a)},gc.lineEnd=function(){n(t,e)}}function se(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function le(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function fe(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function he(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ge(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function pe(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function ve(n){return[Math.atan2(n[1],n[0]),X(n[2])]}function de(n,t){return oa(n[0]-t[0])<Aa&&oa(n[1]-t[1])<Aa}function me(n,t){n*=Na;var e=Math.cos(t*=Na);ye(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function ye(n,t,e){++pc,dc+=(n-dc)/pc,mc+=(t-mc)/pc,yc+=(e-yc)/pc}function xe(){function n(n,u){n*=Na;var i=Math.cos(u*=Na),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);vc+=s,xc+=s*(t+(t=o)),Mc+=s*(e+(e=a)),_c+=s*(r+(r=c)),ye(t,e,r)}var t,e,r;kc.point=function(u,i){u*=Na;var o=Math.cos(i*=Na);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),kc.point=n,ye(t,e,r)}}function Me(){kc.point=me}function _e(){function n(n,t){n*=Na;var e=Math.cos(t*=Na),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-V(g)/h,v=Math.atan2(h,g);bc+=p*s,wc+=p*l,Sc+=p*f,vc+=v,xc+=v*(r+(r=o)),Mc+=v*(u+(u=a)),_c+=v*(i+(i=c)),ye(r,u,i)}var t,e,r,u,i;kc.point=function(o,a){t=o,e=a,kc.point=n,o*=Na;var c=Math.cos(a*=Na);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),ye(r,u,i)},kc.lineEnd=function(){n(t,e),kc.lineEnd=Me,kc.point=me}}function be(){return!0}function we(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(de(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function ke(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ee(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r){if(1&t){n=e[0];var u,r=n.length-1,o=-1;for(i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);return i.lineEnd(),void 0}r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>Sa,k=p*x;if(hc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*ka:_,S^h>=e^m>=e){var E=fe(se(f),se(n));pe(E);var A=fe(u,E);pe(A);var C=(S^_>=0?-1:1)*X(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)<Aa?(n.point(e,r=(r+o)/2>0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)<Aa&&(e-=u*Aa),oa(i-a)<Aa&&(i-=a*Aa),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return oa(o)>Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function ze(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]<t[0]?Sa:-Sa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Re(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)<Aa,N=C||Aa>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)<Aa?k:E):k<=_[1]&&_[1]<=E:A>Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)<Aa?u>0?0:3:oa(r[0]-e)<Aa?u>0?2:1:oa(r[1]-t)<Aa?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),Tc>t&&(Tc=t),t>zc&&(zc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)<Aa||oa(r-h)<Aa?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],L=C-t,T=N-e,q=x*L-y*T;(q*q/M>i||oa((y*L+x*T)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)<Aa?0:o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Sa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=I(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ea]},e):xr}function yr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return oa(u)<Aa?er:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-I(u)*Math.sqrt(n*n+e*e)]},e)}function xr(n,t){return[n,Math.log(Math.tan(Sa/4+t/2))]}function Mr(n){var t,e=Qe(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=Sa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function _r(n,t){return[Math.log(Math.tan(Sa/4+t/2)),-n]}function br(n){return n[0]}function wr(n){return n[1]}function Sr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function Tr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&oa(e-c.circle.x)<Aa&&oa(r-c.circle.cy)<Aa;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Or(c);for(var s=o;s.circle&&oa(e-s.circle.x)<Aa&&oa(r-s.circle.cy)<Aa;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Or(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function zr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)<Aa&&p-u>Aa?{x:f,y:oa(t-f)<Aa?e:p}:oa(u-p)<Aa&&h-r>Aa?{x:oa(e-p)<Aa?t:h,y:p}:oa(r-h)<Aa&&u-g>Aa?{x:h,y:oa(t-h)<Aa?e:g}:oa(u-g)<Aa&&r-f>Aa?{x:oa(e-g)<Aa?t:f,y:g}:null),i.site,null)),++c)}function jr(n,t){return t.angle-n.angle}function Hr(){Jr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Fr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}Wc.insert(y,m),y||(Bc=m)}}}}function Or(n){var t=n.circle;t&&(t.P||(Bc=t.N),Wc.remove(t),Gc.push(t),Jr(t),n.circle=null)}function Yr(n){for(var t,e=Vc,r=De(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Ir(t,n)||!r(t)||oa(t.a.x-t.b.x)<Aa&&oa(t.a.y-t.b.y)<Aa)&&(t.a=t.b=null,e.splice(u,1))}function Ir(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Zr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Vr(n,t,e,r){var u=new Zr(n,t);return Vc.push(u),e&&$r(u,n,t,e),r&&$r(u,t,n,r),Xc[n.i].edges.push(new Br(u,n,t)),Xc[t.i].edges.push(new Br(u,t,n)),u}function Xr(n,t,e){var r=new Zr(n,null);return r.a=t,r.b=e,Vc.push(r),r}function $r(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Br(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Wr(){this._=null}function Jr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Gr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Kr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Qr(n){for(;n.L;)n=n.L;return n}function nu(n,t){var e,r,u,i=n.sort(tu).pop();for(Vc=[],Xc=new Array(n.length),$c=new Wr,Wc=new Wr;;)if(u=Bc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Xc[i.i]=new Pr(i),zr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Yr(t),Ur(t));var o={cells:Xc,edges:Vc};return $c=Wc=Vc=Xc=null,o}function tu(n,t){return t.y-n.y||t.x-n.x}function eu(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function ru(n){return n.x}function uu(n){return n.y}function iu(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function ou(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&ou(n,c[0],e,r,o,a),c[1]&&ou(n,c[1],o,r,u,a),c[2]&&ou(n,c[2],e,a,o,i),c[3]&&ou(n,c[3],o,a,u,i)}}function au(n,t){n=Xo.rgb(n),t=Xo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+vt(Math.round(e+i*n))+vt(Math.round(r+o*n))+vt(Math.round(u+a*n))}}function cu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=fu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function su(n,t){return t-=n=+n,function(e){return n+t*e}}function lu(n,t){var e,r,u,i,o,a=0,c=0,s=[],l=[];for(n+="",t+="",Qc.lastIndex=0,r=0;e=Qc.exec(t);++r)e.index&&s.push(t.substring(a,c=e.index)),l.push({i:s.length,x:e[0]}),s.push(null),a=Qc.lastIndex;for(a<t.length&&s.push(t.substring(a)),r=0,i=l.length;(e=Qc.exec(n))&&i>r;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(zu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*La,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*La:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function zu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ru(n,t){var e,r=[],u=[],i=Xo.transform(n),o=Xo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:su(a[0],c[0])},{i:3,x:su(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Du(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Uu(n){for(var t=n.source,e=n.target,r=Hu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function ju(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Hu(n,t){if(n===t)return n;for(var e=ju(n),r=ju(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Fu(n){n.fixed|=2}function Ou(n){n.fixed&=-7}function Yu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Iu(n){n.fixed&=-5}function Zu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Zu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Vu(n,t){return Xo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wu,n}function Xu(n){return n.children}function $u(n){return n.value}function Bu(n,t){return t.value-n.value}function Wu(n){return Xo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Ju(n){return n.x}function Gu(n){return n.y}function Ku(n,t,e){n.y0=t,n.y=e}function Qu(n){return Xo.range(n.length)}function ni(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ti(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i<u;)t(r=li(e[i],t),n)>0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c<o;)i=u[c],e(i,a),a=i;t(n,r)}e(n,null)}function vi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?Mi(r,u=a):Mi(r=c,u),o--):(xi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)ki(u[i],t,e,r)}function Ei(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function Ai(n){return 1+Xo.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ni(n){var t=n.children;return t&&t.length?Ni(t[0]):n}function Li(n){var t,e=n.children;return e&&(t=e.length)?Li(e[t-1]):n}function Ti(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function qi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function zi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():zi(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Xo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Hi(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=zi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=zi(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++a<c;)i.has(o=r[a])||i.set(o,n.push(o));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(o=n,a=0,t={t:"range",a:arguments},e):o},e.rangePoints=function(u,i){arguments.length<2&&(i=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+i);return o=r(n.length<2?(c+s)/2:c+l*i/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-i+2*c);return o=r(l+h*c,h),s&&o.reverse(),a=h*(1-i),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-i+2*c)),g=f-l-(n.length-i)*h;return o=r(l+Math.round(g/2),h),s&&o.reverse(),a=Math.round(h*(1-i)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return zi(t.a[0])},e.copy=function(){return Ji(n,t)},e.domain(n)}function Gi(n,t){function e(){var e=0,i=t.length;for(u=[];++e<i;)u[e-1]=Xo.quantile(n,e/i);return r}function r(n){return isNaN(n=+n)?void 0:t[Xo.bisect(u,n)]}var u;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(Xo.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return u},r.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?u[e-1]:n[0],e<u.length?u[e]:n[n.length-1]]},r.copy=function(){return Gi(n,t)},e()}function Ki(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=br,r=wr,u=be,i=oo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=Ms.get(n)||oo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function oo(n){return n.join("L")}function ao(n){return oo(n)+"Z"}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function lo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function fo(n,t){return n.length<4?oo(n):n[1]+po(n.slice(1,n.length-1),vo(n,t))}function ho(n,t){return n.length<3?oo(n):n[0]+po((n.push(n[0]),n),vo([n[n.length-2]].concat(n,[n[1]]),t))}function go(n,t){return n.length<3?oo(n):n[0]+po(n,vo(n,t))}function po(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return oo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function vo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function mo(n){if(n.length<3)return oo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",_o(ws,o),",",_o(ws,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),bo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function yo(n){if(n.length<4)return oo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(_o(ws,i)+","+_o(ws,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),bo(e,i,o);return e.join("")}function xo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[_o(ws,o),",",_o(ws,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),bo(t,o,a);return t.join("")}function Mo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return mo(n)}function _o(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function bo(n,t,e){n.push("C",_o(_s,t),",",_o(_s,e),",",_o(bs,t),",",_o(bs,e),",",_o(ws,t),",",_o(ws,e))}function wo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function So(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=wo(u,i);++t<e;)r[t]=(o+(o=wo(u=i,i=n[t+1])))/2;return r[t]=o,r}function ko(n){for(var t,e,r,u,i=[],o=So(n),a=-1,c=n.length-1;++a<c;)t=wo(n[a],n[a+1]),oa(t)<Aa?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ys,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Co(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=_t(e),_=_t(u),b=e===r?function(){return g}:_t(r),w=u===i?function(){return p}:_t(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=br,r=br,u=0,i=wr,o=be,a=oo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=Ms.get(n)||oo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function No(n){return n.radius}function Lo(n){return[n.x,n.y]}function To(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ys;return[e*Math.cos(r),e*Math.sin(r)]}}function qo(){return 64}function zo(){return"circle"}function Ro(n){var t=Math.sqrt(n/Sa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Do(n,t){return fa(n,Ns),n.id=t,n}function Po(n,t,e,r){var u=n.id;return R(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Uo(n){return null==n&&(n=""),function(){this.textContent=n}}function jo(n,t,e,r){var i=n.__transition__||(n.__transition__={active:0,count:0}),o=i[e];if(!o){var a=r.time;o=i[e]={tween:new u,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,Xo.timer(function(r){function u(r){return i.active>e?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]<js[i]/u?i-1:i]:[Os,Yi(n,e)[2]]}return r.invert=function(t){return Io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Io(+e+1),t).length}var i=r.domain(),o=zi(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Pi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=zi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.3"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Xo.mean=function(t,e){var r,u=t.length,i=0,o=-1,a=0;if(1===arguments.length)for(;++o<u;)n(r=t[o])&&(i+=(r-i)/++a);else for(;++o<u;)n(r=e.call(t,t[o],o))&&(i+=(r-i)/++a);return a?i:void 0},Xo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Xo.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)<e?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;e<n.call(t,t[i],i)?u=i:r=i+1}return r}}};var ia=Xo.bisector(function(n){return n});Xo.bisectLeft=ia.left,Xo.bisect=Xo.bisectRight=ia.right,Xo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Xo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Xo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n<e;)for(var u,i=-1,o=r[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return r},Xo.transpose=function(n){return Xo.zip.apply(Xo,n)},Xo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Xo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Xo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Xo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)<t;)i.push(u/o);return i},Xo.map=function(n){var t=new u;if(n instanceof u)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},r(u,{has:i,get:function(n){return this[aa+n]},set:function(n,t){return this[aa+n]=t},remove:o,keys:a,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1),this[t])}});var aa="\x00",ca=aa.charCodeAt(0);Xo.nest=function(){function n(t,a,c){if(c>=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=f(n,t,t[e]);return n};var sa=["webkit","ms","moz","Moz","o","O"];Xo.dispatch=function(){for(var n=new p,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=v(n);return n},p.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=Sizzle,va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return x(i)},da.selectAll=function(n){var t,e,r=[];n=_(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Bo(n.call(e,e.__data__,a,u))),t.parentNode=e);return x(r)};var ma={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Xo.ns={prefix:ma,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!S(n[u]).test(t))return!1;return!0}for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},da.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++r<a;)d=t.call(i=n[r],i.__data__,r),m.has(d)?v[r]=i:m.set(d,i),x.push(d);for(r=-1;++r<f;)d=t.call(e,o=e[r],r),(i=m.get(d))?(g[r]=i,i.__data__=o):y.has(d)||(p[r]=T(o)),y.set(d,o),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],o=e[r],i?(i.__data__=o,g[r]=i):p[r]=T(o);for(;f>r;++r)p[r]=T(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++o<a;)(i=r[o])&&(n[o]=i.__data__);return n}var c=D([]),s=x([]),l=x([]);if("function"==typeof n)for(;++o<a;)e(r=this[o],n.call(r,r.parentNode.__data__,o));else for(;++o<a;)e(r=this[o],n);return s.enter=function(){return c},s.exit=function(){return l},s},da.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},da.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=z.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},da.each=function(n){return R(this,function(t,e,r){n.call(t,t.__data__,e,r)})},da.call=function(n){var t=Bo(arguments);return n.apply(t[0]=this,t),this},da.empty=function(){return!this.node()},da.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return x(o)},ya.insert=function(n,t){return arguments.length<2&&(t=P(this)),da.insert.call(this,n,t)},da.transition=function(){for(var n,t,e=ks||++Ls,r=[],u=Es||{time:Date.now(),ease:yu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&jo(t,c,e,u),n.push(t)}return Do(r,e)},da.interrupt=function(){return this.each(U)},Xo.select=function(n){var t=["string"==typeof n?ha(n,Wo):n];return t.parentNode=Jo,x([t])},Xo.selectAll=function(n){var t=Bo("string"==typeof n?ga(n,Wo):n);return t.parentNode=Jo,x([t])};var xa=Xo.select(Jo);da.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,Ta=Math.SQRT2,qa=2,za=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(Ta*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(Ta*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Ta*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+za*f)/(2*i*qa*h),p=(c*c-i*i-za*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ta;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=T.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=T.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=T.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=T.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",T=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=T.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,T,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv("	","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;zt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)ie(e[r].geometry,t)}},lc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){oe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)oe(e[r],t,0)},Polygon:function(n,t){ae(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)ie(e[r],t)}};Xo.geo.area=function(n){return fc=0,Xo.geo.stream(n,gc),fc};var fc,hc=new re,gc={sphere:function(){fc+=4*Sa},point:g,lineStart:g,lineEnd:g,polygonStart:function(){hc.reset(),gc.lineStart=ce},polygonEnd:function(){var n=2*hc;fc+=0>n?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,gc.polygonStart()},polygonEnd:function(){gc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>hc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,Te,ze,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,Tc,qc,zc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=zc=-(Lc=Tc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,Tc],[qc,zc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=br,r=wr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Xo.geom.polygon=function(n){return fa(n,Zc),n};var Zc=Xo.geom.polygon.prototype=[];Zc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Zc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Zc.clip=function(n){for(var t,e,r,u,i,o,a=Cr(n),c=-1,s=this.length-Cr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Er(o,l,u)?(Er(i,l,u)||n.push(Ar(i,o,l,u)),n.push(o)):Er(i,l,u)&&n.push(Ar(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Vc,Xc,$c,Bc,Wc,Jc=[],Gc=[];Pr.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(jr),t.length},Br.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Wr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=Qr(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Gr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Gr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?Qr(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Gr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Kr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Gr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Gr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Kr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Xo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return nu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&eu(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=_t(r=n),t):r},t.y=function(n){return arguments.length?(o=_t(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Kc:n,t):a===Kc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Kc?null:a&&a[1]},t)};var Kc=[[-1e6,-1e6],[1e6,1e6]];Xo.geom.delaunay=function(n){return Xo.geom.voronoi().triangles(n)},Xo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(oa(c-e)+oa(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=br,c=wr;return(o=arguments.length)?(a=ru,c=uu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Xo.interpolateRgb=au,Xo.interpolateObject=cu,Xo.interpolateNumber=su,Xo.interpolateString=lu;var Qc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;Xo.interpolate=fu,Xo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?au:lu:t instanceof G?au:"object"===e?Array.isArray(t)?hu:cu:su)(n,t)}],Xo.interpolateArray=hu;var ns=function(){return bt},ts=Xo.map({linear:ns,poly:xu,quad:function(){return du},cubic:function(){return mu},sin:function(){return Mu},exp:function(){return _u},circle:function(){return bu},elastic:wu,back:Su,bounce:function(){return ku}}),es=Xo.map({"in":bt,out:pu,"in-out":vu,"out-in":function(n){return vu(pu(n))}});Xo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Uu(n[e]));return t}},Xo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Xo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Xo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(ka-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Xo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++f<s;)l=h[f]=n(c[f],p,a),l.parent=t,g+=l.value;r&&h.sort(r),i&&(t.value=g)}else delete t.children,i&&(t.value=+i.call(e,t,o)||0);return t}function t(n,r){var u=n.children,o=0;if(u&&(a=u.length))for(var a,c=-1,s=r+1;++c<a;)o+=t(u[c],s);else i&&(o=+i.call(e,n,r)||0);return i&&(n.value=o),o}function e(t){var e=[];return n(t,0,e),e}var r=Bu,u=Xu,i=$u;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(u=n,e):u},e.value=function(n){return arguments.length?(i=n,e):i},e.revalue=function(n){return t(n,0),n},e},Xo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Xo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Vu(e,r)},Xo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Xo.sum(o),s=Xo.range(i.length);null!=e&&s.sort(e===as?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=as,r=0,u=ka;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var as={};Xo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Xo.permute(s,f),l=Xo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h<i;)s=r[h],o(s,a),f=c(s,a,f),a=s;vi(n);var g=.5*(l._tree.prelim+s._tree.prelim);t?(u.prelim=t._tree.prelim+e(n,t),u.mod=u.prelim-g):u.prelim=g}else t&&(u.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,u=-1;for(t+=n._tree.mod;++u<r;)a(e[u],t)}}function c(n,t,r){if(t){for(var u,i=n,o=n,a=t,c=n.parent.children[0],s=i._tree.mod,l=o._tree.mod,f=a._tree.mod,h=c._tree.mod;a=si(a),i=ci(i),a&&i;)c=ci(c),o=si(o),o._tree.ancestor=n,u=a._tree.prelim+f-i._tree.prelim-s+e(a,i),u>0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Xo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ti,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ti(t):qi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return qi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ti:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Vu(i,a)},Xo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[])},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(To(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=zo,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),jo(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return Do(i,u)},Ns.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=_(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&jo(u,g,o,i),t.push(u)}return Do(a,o)},Ns.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=Ts,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":Ts,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Ts="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return zs[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]<x[0])],L[1]=f[+(n[1]<x[1])]):x=null),E&&m(n,c,0)&&(e(S),u=!0),A&&m(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,a=Ri(t),c=a[0],s=a[1],p=L[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),T.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),T=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?T.on("touchmove.brush",v).on("touchend.brush",y):T.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),z=+/^n/.test(k);M=[l[1-q]-L[0],f[1-z]-L[1]],L[0]=l[q],L[1]=f[z]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var zs={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(Math.ceil(n/e)*e,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}();'use strict';tv.exportTo('tv.b.ui',function(){var THIS_DOC=document.currentScript.ownerDocument;var svgNS='http://www.w3.org/2000/svg';var highlightIdBoost=tv.b.ui.getColorPaletteHighlightIdBoost();function getColorOfKey(key,selected){var id=tv.b.ui.getColorIdForGeneralPurposeString(key);if(selected)
-id+=highlightIdBoost;return tv.b.ui.getColorPalette()[id];}
-var ChartBase=tv.b.ui.define('svg',undefined,svgNS);ChartBase.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.classList.add('chart-base');this.chartTitle_=undefined;this.data_=undefined;this.seriesKeys_=undefined;this.width_=400;this.height_=300;var template=THIS_DOC.querySelector('#chart-base-template');var svgEl=template.content.querySelector('svg');for(var i=0;i<svgEl.children.length;i++)
+ChromeModelHelper.prototype={get pid(){throw new Error('woah');},get process(){throw new Error('woah');},get model(){return this.model_;},get browserProcess(){return this.browserProcess_;},get browserHelper(){return this.browserHelper_;},get rendererHelpers(){return this.rendererHelpers_;}};return{ChromeModelHelper:ChromeModelHelper};});!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function d(){Xo.event.preventDefault()}function m(){for(var n,t=Xo.event;n=t.sourceEvent;)t=n;return t}function y(n){for(var t=new p,e=0,r=arguments.length;++e<r;)t[arguments[e]]=v(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Xo.event;u.target=n,Xo.event=u,t[u.type].apply(e,r)}finally{Xo.event=i}}},t}function x(n){return fa(n,da),n}function M(n){return"function"==typeof n?n:function(){return ha(n,this)}}function _(n){return"function"==typeof n?n:function(){return ga(n,this)}}function b(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Xo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function w(n){return n.trim().replace(/\s+/g," ")}function S(n){return new RegExp("(?:^|\\s+)"+Xo.requote(n)+"(?:\\s+|$)","g")}function k(n){return n.trim().split(/^|\s+/)}function E(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=k(n).map(A);var u=n.length;return"function"==typeof t?r:e}function A(n){var t=S(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",w(u+" "+n))):e.setAttribute("class",w(u.replace(t," ")))}}function C(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function N(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function L(n){return"function"==typeof n?n:(n=Xo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function T(n){return{__data__:n}}function q(n){return function(){return va(this,n)}}function z(n){return arguments.length||(n=Xo.ascending),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function R(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function U(){var n=this.__transition__;n&&++n.active}function j(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Bo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Xo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=H;a>0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o,a=0,c=0,s=0;if(u=/([a-z]+)\((.*)\)/i.exec(n))switch(i=u[2].split(","),u[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Mt(i[0]),Mt(i[1]),Mt(i[2]))}return(o=Va.get(n))?t(o.r,o.g,o.b):(null!=n&&"#"===n.charAt(0)&&(r=parseInt(n.substring(1),16),isNaN(r)||(4===n.length?(a=(3840&r)>>4,a=a>>4|a,c=240&r,c=c>>4|c,s=15&r,s=s<<4|s):7===n.length&&(a=(16711680&r)>>16,c=(65280&r)>>8,s=255&r))),t(a,c,s))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return $a=n,e}function Nt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*oa(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Xo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function zt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=zt;var r=new zt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=zt;var r=new zt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=uc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&ec!==zt,o=new(i?zt:ec);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=zt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=zt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ft(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ot(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Yt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function It(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Zt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.y=Xt(+r[0]),e+r[0].length):-1}function Vt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Xt(n){return n+(n>68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function re(){}function ue(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function ie(n,t){n&&lc.hasOwnProperty(n.type)&&lc[n.type](n,t)}function oe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ae(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)oe(n[e],t,1);t.polygonEnd()}function ce(){function n(n,t){n*=Na,t=t*Na/2+Sa/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);hc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;gc.point=function(o,a){gc.point=n,r=(t=o)*Na,u=Math.cos(a=(e=a)*Na/2+Sa/4),i=Math.sin(a)},gc.lineEnd=function(){n(t,e)}}function se(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function le(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function fe(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function he(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ge(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function pe(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function ve(n){return[Math.atan2(n[1],n[0]),X(n[2])]}function de(n,t){return oa(n[0]-t[0])<Aa&&oa(n[1]-t[1])<Aa}function me(n,t){n*=Na;var e=Math.cos(t*=Na);ye(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function ye(n,t,e){++pc,dc+=(n-dc)/pc,mc+=(t-mc)/pc,yc+=(e-yc)/pc}function xe(){function n(n,u){n*=Na;var i=Math.cos(u*=Na),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);vc+=s,xc+=s*(t+(t=o)),Mc+=s*(e+(e=a)),_c+=s*(r+(r=c)),ye(t,e,r)}var t,e,r;kc.point=function(u,i){u*=Na;var o=Math.cos(i*=Na);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),kc.point=n,ye(t,e,r)}}function Me(){kc.point=me}function _e(){function n(n,t){n*=Na;var e=Math.cos(t*=Na),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-V(g)/h,v=Math.atan2(h,g);bc+=p*s,wc+=p*l,Sc+=p*f,vc+=v,xc+=v*(r+(r=o)),Mc+=v*(u+(u=a)),_c+=v*(i+(i=c)),ye(r,u,i)}var t,e,r,u,i;kc.point=function(o,a){t=o,e=a,kc.point=n,o*=Na;var c=Math.cos(a*=Na);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),ye(r,u,i)},kc.lineEnd=function(){n(t,e),kc.lineEnd=Me,kc.point=me}}function be(){return!0}function we(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(de(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function ke(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ee(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r){if(1&t){n=e[0];var u,r=n.length-1,o=-1;for(i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);return i.lineEnd(),void 0}r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>Sa,k=p*x;if(hc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*ka:_,S^h>=e^m>=e){var E=fe(se(f),se(n));pe(E);var A=fe(u,E);pe(A);var C=(S^_>=0?-1:1)*X(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)<Aa?(n.point(e,r=(r+o)/2>0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)<Aa&&(e-=u*Aa),oa(i-a)<Aa&&(i-=a*Aa),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return oa(o)>Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function ze(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]<t[0]?Sa:-Sa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Re(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)<Aa,N=C||Aa>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)<Aa?k:E):k<=_[1]&&_[1]<=E:A>Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)<Aa?u>0?0:3:oa(r[0]-e)<Aa?u>0?2:1:oa(r[1]-t)<Aa?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),Tc>t&&(Tc=t),t>zc&&(zc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)<Aa||oa(r-h)<Aa?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],L=C-t,T=N-e,q=x*L-y*T;(q*q/M>i||oa((y*L+x*T)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)<Aa?0:o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Sa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=I(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ea]},e):xr}function yr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return oa(u)<Aa?er:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-I(u)*Math.sqrt(n*n+e*e)]},e)}function xr(n,t){return[n,Math.log(Math.tan(Sa/4+t/2))]}function Mr(n){var t,e=Qe(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=Sa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function _r(n,t){return[Math.log(Math.tan(Sa/4+t/2)),-n]}function br(n){return n[0]}function wr(n){return n[1]}function Sr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function Tr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&oa(e-c.circle.x)<Aa&&oa(r-c.circle.cy)<Aa;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Or(c);for(var s=o;s.circle&&oa(e-s.circle.x)<Aa&&oa(r-s.circle.cy)<Aa;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Or(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function zr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)<Aa&&p-u>Aa?{x:f,y:oa(t-f)<Aa?e:p}:oa(u-p)<Aa&&h-r>Aa?{x:oa(e-p)<Aa?t:h,y:p}:oa(r-h)<Aa&&u-g>Aa?{x:h,y:oa(t-h)<Aa?e:g}:oa(u-g)<Aa&&r-f>Aa?{x:oa(e-g)<Aa?t:f,y:g}:null),i.site,null)),++c)}function jr(n,t){return t.angle-n.angle}function Hr(){Jr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Fr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}Wc.insert(y,m),y||(Bc=m)}}}}function Or(n){var t=n.circle;t&&(t.P||(Bc=t.N),Wc.remove(t),Gc.push(t),Jr(t),n.circle=null)}function Yr(n){for(var t,e=Vc,r=De(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Ir(t,n)||!r(t)||oa(t.a.x-t.b.x)<Aa&&oa(t.a.y-t.b.y)<Aa)&&(t.a=t.b=null,e.splice(u,1))}function Ir(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Zr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Vr(n,t,e,r){var u=new Zr(n,t);return Vc.push(u),e&&$r(u,n,t,e),r&&$r(u,t,n,r),Xc[n.i].edges.push(new Br(u,n,t)),Xc[t.i].edges.push(new Br(u,t,n)),u}function Xr(n,t,e){var r=new Zr(n,null);return r.a=t,r.b=e,Vc.push(r),r}function $r(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Br(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Wr(){this._=null}function Jr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Gr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Kr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Qr(n){for(;n.L;)n=n.L;return n}function nu(n,t){var e,r,u,i=n.sort(tu).pop();for(Vc=[],Xc=new Array(n.length),$c=new Wr,Wc=new Wr;;)if(u=Bc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Xc[i.i]=new Pr(i),zr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Yr(t),Ur(t));var o={cells:Xc,edges:Vc};return $c=Wc=Vc=Xc=null,o}function tu(n,t){return t.y-n.y||t.x-n.x}function eu(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function ru(n){return n.x}function uu(n){return n.y}function iu(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function ou(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&ou(n,c[0],e,r,o,a),c[1]&&ou(n,c[1],o,r,u,a),c[2]&&ou(n,c[2],e,a,o,i),c[3]&&ou(n,c[3],o,a,u,i)}}function au(n,t){n=Xo.rgb(n),t=Xo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+vt(Math.round(e+i*n))+vt(Math.round(r+o*n))+vt(Math.round(u+a*n))}}function cu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=fu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function su(n,t){return t-=n=+n,function(e){return n+t*e}}function lu(n,t){var e,r,u,i,o,a=0,c=0,s=[],l=[];for(n+="",t+="",Qc.lastIndex=0,r=0;e=Qc.exec(t);++r)e.index&&s.push(t.substring(a,c=e.index)),l.push({i:s.length,x:e[0]}),s.push(null),a=Qc.lastIndex;for(a<t.length&&s.push(t.substring(a)),r=0,i=l.length;(e=Qc.exec(n))&&i>r;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(zu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*La,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*La:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function zu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ru(n,t){var e,r=[],u=[],i=Xo.transform(n),o=Xo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:su(a[0],c[0])},{i:3,x:su(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Du(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Uu(n){for(var t=n.source,e=n.target,r=Hu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function ju(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Hu(n,t){if(n===t)return n;for(var e=ju(n),r=ju(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Fu(n){n.fixed|=2}function Ou(n){n.fixed&=-7}function Yu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Iu(n){n.fixed&=-5}function Zu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Zu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Vu(n,t){return Xo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wu,n}function Xu(n){return n.children}function $u(n){return n.value}function Bu(n,t){return t.value-n.value}function Wu(n){return Xo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Ju(n){return n.x}function Gu(n){return n.y}function Ku(n,t,e){n.y0=t,n.y=e}function Qu(n){return Xo.range(n.length)}function ni(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ti(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i<u;)t(r=li(e[i],t),n)>0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c<o;)i=u[c],e(i,a),a=i;t(n,r)}e(n,null)}function vi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?Mi(r,u=a):Mi(r=c,u),o--):(xi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)ki(u[i],t,e,r)}function Ei(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function Ai(n){return 1+Xo.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ni(n){var t=n.children;return t&&t.length?Ni(t[0]):n}function Li(n){var t,e=n.children;return e&&(t=e.length)?Li(e[t-1]):n}function Ti(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function qi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function zi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():zi(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Xo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Hi(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=zi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=zi(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++a<c;)i.has(o=r[a])||i.set(o,n.push(o));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(o=n,a=0,t={t:"range",a:arguments},e):o},e.rangePoints=function(u,i){arguments.length<2&&(i=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+i);return o=r(n.length<2?(c+s)/2:c+l*i/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-i+2*c);return o=r(l+h*c,h),s&&o.reverse(),a=h*(1-i),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-i+2*c)),g=f-l-(n.length-i)*h;return o=r(l+Math.round(g/2),h),s&&o.reverse(),a=Math.round(h*(1-i)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return zi(t.a[0])},e.copy=function(){return Ji(n,t)},e.domain(n)}function Gi(n,t){function e(){var e=0,i=t.length;for(u=[];++e<i;)u[e-1]=Xo.quantile(n,e/i);return r}function r(n){return isNaN(n=+n)?void 0:t[Xo.bisect(u,n)]}var u;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(Xo.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return u},r.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?u[e-1]:n[0],e<u.length?u[e]:n[n.length-1]]},r.copy=function(){return Gi(n,t)},e()}function Ki(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=br,r=wr,u=be,i=oo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=Ms.get(n)||oo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function oo(n){return n.join("L")}function ao(n){return oo(n)+"Z"}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function lo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function fo(n,t){return n.length<4?oo(n):n[1]+po(n.slice(1,n.length-1),vo(n,t))}function ho(n,t){return n.length<3?oo(n):n[0]+po((n.push(n[0]),n),vo([n[n.length-2]].concat(n,[n[1]]),t))}function go(n,t){return n.length<3?oo(n):n[0]+po(n,vo(n,t))}function po(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return oo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function vo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function mo(n){if(n.length<3)return oo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",_o(ws,o),",",_o(ws,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),bo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function yo(n){if(n.length<4)return oo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(_o(ws,i)+","+_o(ws,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),bo(e,i,o);return e.join("")}function xo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[_o(ws,o),",",_o(ws,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),bo(t,o,a);return t.join("")}function Mo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return mo(n)}function _o(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function bo(n,t,e){n.push("C",_o(_s,t),",",_o(_s,e),",",_o(bs,t),",",_o(bs,e),",",_o(ws,t),",",_o(ws,e))}function wo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function So(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=wo(u,i);++t<e;)r[t]=(o+(o=wo(u=i,i=n[t+1])))/2;return r[t]=o,r}function ko(n){for(var t,e,r,u,i=[],o=So(n),a=-1,c=n.length-1;++a<c;)t=wo(n[a],n[a+1]),oa(t)<Aa?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ys,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Co(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=_t(e),_=_t(u),b=e===r?function(){return g}:_t(r),w=u===i?function(){return p}:_t(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=br,r=br,u=0,i=wr,o=be,a=oo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=Ms.get(n)||oo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function No(n){return n.radius}function Lo(n){return[n.x,n.y]}function To(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ys;return[e*Math.cos(r),e*Math.sin(r)]}}function qo(){return 64}function zo(){return"circle"}function Ro(n){var t=Math.sqrt(n/Sa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Do(n,t){return fa(n,Ns),n.id=t,n}function Po(n,t,e,r){var u=n.id;return R(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Uo(n){return null==n&&(n=""),function(){this.textContent=n}}function jo(n,t,e,r){var i=n.__transition__||(n.__transition__={active:0,count:0}),o=i[e];if(!o){var a=r.time;o=i[e]={tween:new u,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,Xo.timer(function(r){function u(r){return i.active>e?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]<js[i]/u?i-1:i]:[Os,Yi(n,e)[2]]}return r.invert=function(t){return Io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Io(+e+1),t).length}var i=r.domain(),o=zi(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Pi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=zi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.3"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Xo.mean=function(t,e){var r,u=t.length,i=0,o=-1,a=0;if(1===arguments.length)for(;++o<u;)n(r=t[o])&&(i+=(r-i)/++a);else for(;++o<u;)n(r=e.call(t,t[o],o))&&(i+=(r-i)/++a);return a?i:void 0},Xo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Xo.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)<e?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;e<n.call(t,t[i],i)?u=i:r=i+1}return r}}};var ia=Xo.bisector(function(n){return n});Xo.bisectLeft=ia.left,Xo.bisect=Xo.bisectRight=ia.right,Xo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Xo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Xo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n<e;)for(var u,i=-1,o=r[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return r},Xo.transpose=function(n){return Xo.zip.apply(Xo,n)},Xo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Xo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Xo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Xo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)<t;)i.push(u/o);return i},Xo.map=function(n){var t=new u;if(n instanceof u)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},r(u,{has:i,get:function(n){return this[aa+n]},set:function(n,t){return this[aa+n]=t},remove:o,keys:a,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1),this[t])}});var aa="\x00",ca=aa.charCodeAt(0);Xo.nest=function(){function n(t,a,c){if(c>=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=f(n,t,t[e]);return n};var sa=["webkit","ms","moz","Moz","o","O"];Xo.dispatch=function(){for(var n=new p,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=v(n);return n},p.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=Sizzle,va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return x(i)},da.selectAll=function(n){var t,e,r=[];n=_(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Bo(n.call(e,e.__data__,a,u))),t.parentNode=e);return x(r)};var ma={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Xo.ns={prefix:ma,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!S(n[u]).test(t))return!1;return!0}for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},da.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++r<a;)d=t.call(i=n[r],i.__data__,r),m.has(d)?v[r]=i:m.set(d,i),x.push(d);for(r=-1;++r<f;)d=t.call(e,o=e[r],r),(i=m.get(d))?(g[r]=i,i.__data__=o):y.has(d)||(p[r]=T(o)),y.set(d,o),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],o=e[r],i?(i.__data__=o,g[r]=i):p[r]=T(o);for(;f>r;++r)p[r]=T(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++o<a;)(i=r[o])&&(n[o]=i.__data__);return n}var c=D([]),s=x([]),l=x([]);if("function"==typeof n)for(;++o<a;)e(r=this[o],n.call(r,r.parentNode.__data__,o));else for(;++o<a;)e(r=this[o],n);return s.enter=function(){return c},s.exit=function(){return l},s},da.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},da.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=z.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},da.each=function(n){return R(this,function(t,e,r){n.call(t,t.__data__,e,r)})},da.call=function(n){var t=Bo(arguments);return n.apply(t[0]=this,t),this},da.empty=function(){return!this.node()},da.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return x(o)},ya.insert=function(n,t){return arguments.length<2&&(t=P(this)),da.insert.call(this,n,t)},da.transition=function(){for(var n,t,e=ks||++Ls,r=[],u=Es||{time:Date.now(),ease:yu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&jo(t,c,e,u),n.push(t)}return Do(r,e)},da.interrupt=function(){return this.each(U)},Xo.select=function(n){var t=["string"==typeof n?ha(n,Wo):n];return t.parentNode=Jo,x([t])},Xo.selectAll=function(n){var t=Bo("string"==typeof n?ga(n,Wo):n);return t.parentNode=Jo,x([t])};var xa=Xo.select(Jo);da.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,Ta=Math.SQRT2,qa=2,za=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(Ta*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(Ta*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Ta*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+za*f)/(2*i*qa*h),p=(c*c-i*i-za*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ta;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=T.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=T.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=T.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=T.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",T=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=T.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,T,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv("	","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;zt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)ie(e[r].geometry,t)}},lc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){oe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)oe(e[r],t,0)},Polygon:function(n,t){ae(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)ie(e[r],t)}};Xo.geo.area=function(n){return fc=0,Xo.geo.stream(n,gc),fc};var fc,hc=new re,gc={sphere:function(){fc+=4*Sa},point:g,lineStart:g,lineEnd:g,polygonStart:function(){hc.reset(),gc.lineStart=ce},polygonEnd:function(){var n=2*hc;fc+=0>n?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,gc.polygonStart()},polygonEnd:function(){gc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>hc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,Te,ze,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,Tc,qc,zc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=zc=-(Lc=Tc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,Tc],[qc,zc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=br,r=wr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Xo.geom.polygon=function(n){return fa(n,Zc),n};var Zc=Xo.geom.polygon.prototype=[];Zc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Zc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Zc.clip=function(n){for(var t,e,r,u,i,o,a=Cr(n),c=-1,s=this.length-Cr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Er(o,l,u)?(Er(i,l,u)||n.push(Ar(i,o,l,u)),n.push(o)):Er(i,l,u)&&n.push(Ar(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Vc,Xc,$c,Bc,Wc,Jc=[],Gc=[];Pr.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(jr),t.length},Br.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Wr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=Qr(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Gr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Gr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?Qr(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Gr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Kr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Gr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Gr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Kr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Xo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return nu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&eu(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=_t(r=n),t):r},t.y=function(n){return arguments.length?(o=_t(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Kc:n,t):a===Kc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Kc?null:a&&a[1]},t)};var Kc=[[-1e6,-1e6],[1e6,1e6]];Xo.geom.delaunay=function(n){return Xo.geom.voronoi().triangles(n)},Xo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(oa(c-e)+oa(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=br,c=wr;return(o=arguments.length)?(a=ru,c=uu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Xo.interpolateRgb=au,Xo.interpolateObject=cu,Xo.interpolateNumber=su,Xo.interpolateString=lu;var Qc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;Xo.interpolate=fu,Xo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?au:lu:t instanceof G?au:"object"===e?Array.isArray(t)?hu:cu:su)(n,t)}],Xo.interpolateArray=hu;var ns=function(){return bt},ts=Xo.map({linear:ns,poly:xu,quad:function(){return du},cubic:function(){return mu},sin:function(){return Mu},exp:function(){return _u},circle:function(){return bu},elastic:wu,back:Su,bounce:function(){return ku}}),es=Xo.map({"in":bt,out:pu,"in-out":vu,"out-in":function(n){return vu(pu(n))}});Xo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Uu(n[e]));return t}},Xo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Xo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Xo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(ka-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Xo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++f<s;)l=h[f]=n(c[f],p,a),l.parent=t,g+=l.value;r&&h.sort(r),i&&(t.value=g)}else delete t.children,i&&(t.value=+i.call(e,t,o)||0);return t}function t(n,r){var u=n.children,o=0;if(u&&(a=u.length))for(var a,c=-1,s=r+1;++c<a;)o+=t(u[c],s);else i&&(o=+i.call(e,n,r)||0);return i&&(n.value=o),o}function e(t){var e=[];return n(t,0,e),e}var r=Bu,u=Xu,i=$u;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(u=n,e):u},e.value=function(n){return arguments.length?(i=n,e):i},e.revalue=function(n){return t(n,0),n},e},Xo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Xo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Vu(e,r)},Xo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Xo.sum(o),s=Xo.range(i.length);null!=e&&s.sort(e===as?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=as,r=0,u=ka;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var as={};Xo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Xo.permute(s,f),l=Xo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h<i;)s=r[h],o(s,a),f=c(s,a,f),a=s;vi(n);var g=.5*(l._tree.prelim+s._tree.prelim);t?(u.prelim=t._tree.prelim+e(n,t),u.mod=u.prelim-g):u.prelim=g}else t&&(u.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,u=-1;for(t+=n._tree.mod;++u<r;)a(e[u],t)}}function c(n,t,r){if(t){for(var u,i=n,o=n,a=t,c=n.parent.children[0],s=i._tree.mod,l=o._tree.mod,f=a._tree.mod,h=c._tree.mod;a=si(a),i=ci(i),a&&i;)c=ci(c),o=si(o),o._tree.ancestor=n,u=a._tree.prelim+f-i._tree.prelim-s+e(a,i),u>0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Xo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ti,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ti(t):qi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return qi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ti:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Vu(i,a)},Xo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[])},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(To(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=zo,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),jo(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return Do(i,u)},Ns.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=_(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&jo(u,g,o,i),t.push(u)}return Do(a,o)},Ns.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=Ts,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":Ts,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Ts="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return zs[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]<x[0])],L[1]=f[+(n[1]<x[1])]):x=null),E&&m(n,c,0)&&(e(S),u=!0),A&&m(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,a=Ri(t),c=a[0],s=a[1],p=L[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),T.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),T=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?T.on("touchmove.brush",v).on("touchend.brush",y):T.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),z=+/^n/.test(k);M=[l[1-q]-L[0],f[1-z]-L[1]],L[0]=l[q],L[1]=f[z]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var zs={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(Math.ceil(n/e)*e,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}();'use strict';tr.exportTo('tr.b.ui',function(){var THIS_DOC=document.currentScript.ownerDocument;var svgNS='http://www.w3.org/2000/svg';var highlightIdBoost=tr.b.ui.getColorPaletteHighlightIdBoost();function getColorOfKey(key,selected){var id=tr.b.ui.getColorIdForGeneralPurposeString(key);if(selected)
+id+=highlightIdBoost;return tr.b.ui.getColorPalette()[id];}
+var ChartBase=tr.b.ui.define('svg',undefined,svgNS);ChartBase.prototype={__proto__:HTMLUnknownElement.prototype,decorate:function(){this.classList.add('chart-base');this.chartTitle_=undefined;this.data_=undefined;this.seriesKeys_=undefined;this.width_=400;this.height_=300;var template=THIS_DOC.querySelector('#chart-base-template');var svgEl=template.content.querySelector('svg');for(var i=0;i<svgEl.children.length;i++)
 this.appendChild(svgEl.children[i].cloneNode(true));Object.defineProperty(this,'width',{get:function(){return this.width_;},set:function(width){this.width_=width;this.updateContents_();}});Object.defineProperty(this,'height',{get:function(){return this.height_;},set:function(height){this.height_=height;this.updateContents_();}});},get chartTitle(){return chartTitle_;},set chartTitle(chartTitle){this.chartTitle_=chartTitle;this.updateContents_();},get chartAreaElement(){return this.querySelector('#chart-area');},get data(){return this.data_;},setSize:function(size){this.width_=size.width;this.height_=size.height;this.updateContents_();},get margin(){var margin={top:20,right:20,bottom:30,left:50};if(this.chartTitle_)
 margin.top+=20;return margin;},get chartAreaSize(){var margin=this.margin;return{width:this.width_-margin.left-margin.right,height:this.height_-margin.top-margin.bottom};},getLegendKeys_:function(){throw new Error('Not implemented');},updateScales_:function(width,height){throw new Error('Not implemented');},updateContents_:function(){var margin=this.margin;var width=this.chartAreaSize.width;var height=this.chartAreaSize.height;var thisSel=d3.select(this);thisSel.attr('width',this.width_);thisSel.attr('height',this.height_);var chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.attr('transform','translate('+margin.left+','+margin.top+')');this.updateScales_(width,height);if(this.xScale_&&this.yScale_){var xAxisRenderer=d3.svg.axis().scale(this.xScale_).orient('bottom');var yAxisRenderer=d3.svg.axis().scale(this.yScale_).orient('left');chartAreaSel.select('.x.axis').attr('transform','translate(0,'+height+')').call(xAxisRenderer);chartAreaSel.select('.y.axis').call(yAxisRenderer);}
 var titleSel=chartAreaSel.select('#title');if(this.chartTitle_){titleSel.attr('transform','translate('+width*0.5+',-5)').style('display',undefined).style('text-anchor','middle').attr('class','title').attr('width',width).text(this.chartTitle_);}else{titleSel.style('display','none');}
@@ -3990,29 +4066,30 @@
 throw new Error('push cannot nest');this.tempHighlightedLegendKey_=key;this.updateHighlight_();},popTempHighlightedLegendKey:function(key){if(this.tempHighlightedLegendKey_!=key)
 throw new Error('pop cannot happen');this.tempHighlightedLegendKey_=undefined;this.updateHighlight_();},updateHighlight_:function(){var chartAreaSel=d3.select(this.chartAreaElement);var legendEntriesSel=chartAreaSel.selectAll('.legend');var that=this;legendEntriesSel.each(function(key){var highlighted=key==that.currentHighlightedLegendKey;var color=getColorOfKey(key,highlighted);this.style.fill=color;if(highlighted)
 this.style.fontWeight='bold';else
-this.style.fontWeight='';});}};return{getColorOfKey:getColorOfKey,ChartBase:ChartBase};});'use strict';tv.exportTo('tv.b.ui',function(){var ChartBase=tv.b.ui.ChartBase;var getColorOfKey=tv.b.ui.getColorOfKey;function getSampleWidth(data,index,leftSide){var leftIndex,rightIndex;if(leftSide){leftIndex=Math.max(index-1,0);rightIndex=index;}else{leftIndex=index;rightIndex=Math.min(index+1,data.length-1);}
+this.style.fontWeight='';});}};return{getColorOfKey:getColorOfKey,ChartBase:ChartBase};});'use strict';tr.exportTo('tr.b.ui',function(){var ChartBase=tr.b.ui.ChartBase;var getColorOfKey=tr.b.ui.getColorOfKey;function getSampleWidth(data,index,leftSide){var leftIndex,rightIndex;if(leftSide){leftIndex=Math.max(index-1,0);rightIndex=index;}else{leftIndex=index;rightIndex=Math.min(index+1,data.length-1);}
 var leftWidth=data[index].x-data[leftIndex].x;var rightWidth=data[rightIndex].x-data[index].x;return leftWidth*0.5+rightWidth*0.5;}
-var LineChart=tv.b.ui.define('line-chart',ChartBase);LineChart.prototype={__proto__:ChartBase.prototype,decorate:function(){ChartBase.prototype.decorate.call(this);this.classList.add('line-chart');this.brushedRange_=new tv.b.Range();this.xScale_=d3.scale.linear();this.yScale_=d3.scale.linear();d3.select(this.chartAreaElement).append('g').attr('id','brushes');d3.select(this.chartAreaElement).append('g').attr('id','series');this.addEventListener('mousedown',this.onMouseDown_.bind(this));},set data(data){if(data.length==0)
+var LineChart=tr.b.ui.define('line-chart',ChartBase);LineChart.prototype={__proto__:ChartBase.prototype,decorate:function(){ChartBase.prototype.decorate.call(this);this.classList.add('line-chart');this.brushedRange_=new tr.b.Range();this.xScale_=d3.scale.linear();this.yScale_=d3.scale.linear();d3.select(this.chartAreaElement).append('g').attr('id','brushes');d3.select(this.chartAreaElement).append('g').attr('id','series');this.addEventListener('mousedown',this.onMouseDown_.bind(this));},set data(data){if(data.length==0)
 throw new Error('Data must be nonzero. Pass undefined.');var keys;if(data!==undefined){var d=data[0];if(d.x===undefined)
 throw new Error('Elements must have "x" fields');keys=d3.keys(data[0]);keys.splice(keys.indexOf('x'),1);if(keys.length==0)
 throw new Error('Elements must have at least one other field than X');}else{keys=undefined;}
-this.data_=data;this.seriesKeys_=keys;this.updateContents_();},set brushedRange(range){this.brushedRange_.reset();this.brushedRange_.addRange(range);this.updateContents_();},computeBrushRangeFromIndices:function(indexA,indexB){var r=new tv.b.Range();var leftIndex=Math.min(indexA,indexB);var rightIndex=Math.max(indexA,indexB);leftIndex=Math.max(0,leftIndex);rightIndex=Math.min(this.data_.length-1,rightIndex);r.addValue(this.data_[leftIndex].x-
+this.data_=data;this.seriesKeys_=keys;this.updateContents_();},set brushedRange(range){this.brushedRange_.reset();this.brushedRange_.addRange(range);this.updateContents_();},computeBrushRangeFromIndices:function(indexA,indexB){var r=new tr.b.Range();var leftIndex=Math.min(indexA,indexB);var rightIndex=Math.max(indexA,indexB);leftIndex=Math.max(0,leftIndex);rightIndex=Math.min(this.data_.length-1,rightIndex);r.addValue(this.data_[leftIndex].x-
 getSampleWidth(this.data_,leftIndex,true));r.addValue(this.data_[rightIndex].x+
 getSampleWidth(this.data_,rightIndex,false));return r;},getLegendKeys_:function(){if(this.seriesKeys_&&this.seriesKeys_.length>1)
 return this.seriesKeys_.slice();return[];},updateScales_:function(width,height){if(this.data_===undefined)
-return;this.xScale_.range([0,width]);this.xScale_.domain(d3.extent(this.data_,function(d){return d.x;}));var yRange=new tv.b.Range();this.data_.forEach(function(d){this.seriesKeys_.forEach(function(k){yRange.addValue(d[k]);});},this);this.yScale_.range([height,0]);this.yScale_.domain([yRange.min,yRange.max]);},updateContents_:function(){ChartBase.prototype.updateContents_.call(this);if(!this.data_)
+return;this.xScale_.range([0,width]);this.xScale_.domain(d3.extent(this.data_,function(d){return d.x;}));var yRange=new tr.b.Range();this.data_.forEach(function(d){this.seriesKeys_.forEach(function(k){yRange.addValue(d[k]);});},this);this.yScale_.range([height,0]);this.yScale_.domain([yRange.min,yRange.max]);},updateContents_:function(){ChartBase.prototype.updateContents_.call(this);if(!this.data_)
 return;var chartAreaSel=d3.select(this.chartAreaElement);var brushes=this.brushedRange_.isEmpty?[]:[this.brushedRange_];var brushRectsSel=chartAreaSel.select('#brushes').selectAll('rect').data(brushes);brushRectsSel.enter().append('rect');brushRectsSel.exit().remove();brushRectsSel.attr('x',function(d){return this.xScale_(d.min);}.bind(this)).attr('y',0).attr('width',function(d){return this.xScale_(d.max)-this.xScale_(d.min);}.bind(this)).attr('height',this.chartAreaSize.height);var seriesSel=chartAreaSel.select('#series');var pathsSel=seriesSel.selectAll('path').data(this.seriesKeys_);pathsSel.enter().append('path').attr('class','line').style('stroke',function(key){return getColorOfKey(key);}).attr('d',function(key){var line=d3.svg.line().x(function(d){return this.xScale_(d.x);}.bind(this)).y(function(d){return this.yScale_(d[key]);}.bind(this));return line(this.data_);}.bind(this));pathsSel.exit().remove();},getDataIndexAtClientPoint_:function(clientX,clientY,clipToY){var rect=this.getBoundingClientRect();var margin=this.margin;var chartAreaSize=this.chartAreaSize;var x=clientX-rect.left-margin.left;var y=clientY-rect.top-margin.top;if(clipToY){if(y<0||y>=chartAreaSize.height)
 return undefined;}
 var dataX=this.xScale_.invert(x);var index;if(this.data_){var bisect=d3.bisector(function(d){return d.x;}).right;index=bisect(this.data_,dataX)-1;}
-return index;},onMouseDown_:function(e){var index=this.getDataIndexAtClientPoint_(e.clientX,e.clientY,true);if(index!==undefined){tv.b.ui.trackMouseMovesUntilMouseUp(this.onMouseMove_.bind(this,e.button),this.onMouseUp_.bind(this,e.button));}
+return index;},onMouseDown_:function(e){var index=this.getDataIndexAtClientPoint_(e.clientX,e.clientY,true);if(index!==undefined){tr.b.ui.trackMouseMovesUntilMouseUp(this.onMouseMove_.bind(this,e.button),this.onMouseUp_.bind(this,e.button));}
 e.preventDefault();e.stopPropagation();var event=new Event('item-mousedown');event.data=this.data_[index];event.index=index;event.buttons=e.buttons;this.dispatchEvent(event);},onMouseMove_:function(button,e){var index=this.getDataIndexAtClientPoint_(e.clientX,e.clientY,false);if(e.buttons!==undefined){e.preventDefault();e.stopPropagation();}
-var event=new Event('item-mousemove');event.data=this.data_[index];event.index=index;event.button=button;this.dispatchEvent(event);},onMouseUp_:function(button,e){var index=this.getDataIndexAtClientPoint_(e.clientX,e.clientY,false);e.preventDefault();e.stopPropagation();var event=new Event('item-mouseup');event.data=this.data_[index];event.index=index;event.button=button;this.dispatchEvent(event);}};return{LineChart:LineChart};});'use strict';Polymer('tv-e-analysis-side-panel-alerts',{ready:function(){this.rangeOfInterest_=new tv.b.Range();this.selection_=undefined;},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();},get listeningToKeys(){return false;},set selection(selection){},set rangeOfInterest(rangeOfInterest){},selectAlertsOfType:function(alertTypeString){var alertsOfType=this.model_.alerts.filter(function(alert){return alert.title===alertTypeString;});var event=new tv.c.RequestSelectionChangeEvent();event.selection=new tv.c.Selection(alertsOfType);this.dispatchEvent(event);},alertsByType_:function(alerts){var alertsByType={};alerts.forEach(function(alert){if(!alertsByType[alert.title])
-alertsByType[alert.title]=[];alertsByType[alert.title].push(alert);});return alertsByType;},alertsTableRows_:function(alertsByType){return Object.keys(alertsByType).map(function(key){return{alertType:key,count:alertsByType[key].length};});},alertsTableColumns_:function(){return[{title:'Alert type',value:function(row){return row.alertType;},width:'180px'},{title:'Count',width:'100%',value:function(row){return row.count;}}];},createAlertsTable_:function(alerts){var alertsByType=this.alertsByType_(alerts);var table=document.createElement('tracing-analysis-nested-table');table.tableColumns=this.alertsTableColumns_();table.tableRows=this.alertsTableRows_(alertsByType);table.supportsSelection=true;table.addEventListener('selection-changed',function(e){var row=table.selectedTableRow;if(row)
+var event=new Event('item-mousemove');event.data=this.data_[index];event.index=index;event.button=button;this.dispatchEvent(event);},onMouseUp_:function(button,e){var index=this.getDataIndexAtClientPoint_(e.clientX,e.clientY,false);e.preventDefault();e.stopPropagation();var event=new Event('item-mouseup');event.data=this.data_[index];event.index=index;event.button=button;this.dispatchEvent(event);}};return{LineChart:LineChart};});'use strict';Polymer('tr-e-s-alerts-side-panel',{ready:function(){this.rangeOfInterest_=new tr.b.Range();this.selection_=undefined;},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();},get listeningToKeys(){return false;},set selection(selection){},set rangeOfInterest(rangeOfInterest){},selectAlertsOfType:function(alertTypeString){var alertsOfType=this.model_.alerts.filter(function(alert){return alert.title===alertTypeString;});var event=new tr.c.RequestSelectionChangeEvent();event.selection=new tr.c.Selection(alertsOfType);this.dispatchEvent(event);},alertsByType_:function(alerts){var alertsByType={};alerts.forEach(function(alert){if(!alertsByType[alert.title])
+alertsByType[alert.title]=[];alertsByType[alert.title].push(alert);});return alertsByType;},alertsTableRows_:function(alertsByType){return Object.keys(alertsByType).map(function(key){return{alertType:key,count:alertsByType[key].length};});},alertsTableColumns_:function(){return[{title:'Alert type',value:function(row){return row.alertType;},width:'180px'},{title:'Count',width:'100%',value:function(row){return row.count;}}];},createAlertsTable_:function(alerts){var alertsByType=this.alertsByType_(alerts);var table=document.createElement('tr-b-ui-table');table.tableColumns=this.alertsTableColumns_();table.tableRows=this.alertsTableRows_(alertsByType);table.supportsSelection=true;table.addEventListener('selection-changed',function(e){var row=table.selectedTableRow;if(row)
 this.selectAlertsOfType(row.alertType);}.bind(this));return table;},updateContents_:function(){this.$.result_area.textContent='';if(this.model_===undefined)
 return;var panel=this.createAlertsTable_(this.model_.alerts);this.$.result_area.appendChild(panel);},supportsModel:function(m){if(m==undefined){return{supported:false,reason:'Unknown tracing model'};}else if(m.alerts.length===0){return{supported:false,reason:'No alerts in tracing model'};}
-return{supported:true};},textLabel:'Alerts'});'use strict';tv.exportTo('tv.c.trace_model',function(){var Statistics=tv.b.Statistics;var FRAME_PERF_CLASS={GOOD:'good',BAD:'bad',TERRIBLE:'terrible',NEUTRAL:'generic_work'};function Frame(associatedEvents,threadTimeRanges,opt_args){tv.c.trace_model.Event.call(this);this.threadTimeRanges=threadTimeRanges;this.associatedEvents=associatedEvents;this.args=opt_args||{};this.title='Frame';this.start=Statistics.min(threadTimeRanges,function(x){return x.start;});this.end=Statistics.max(threadTimeRanges,function(x){return x.end;});this.totalDuration=Statistics.sum(threadTimeRanges,function(x){return x.end-x.start;});this.perfClass=FRAME_PERF_CLASS.NEUTRAL;};Frame.prototype={__proto__:tv.c.trace_model.Event.prototype,set perfClass(perfClass){this.colorId=tv.b.ui.getColorIdForReservedName(perfClass);this.perfClass_=perfClass;},get perfClass(){return this.perfClass_;},shiftTimestampsForward:function(amount){this.start+=amount;this.end+=amount;for(var i=0;i<this.threadTimeRanges.length;i++){this.threadTimeRanges[i].start+=amount;this.threadTimeRanges[i].end+=amount;}},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);}};tv.c.trace_model.EventRegistry.register(Frame,{name:'frame',pluralName:'frames',singleViewElementName:'tv-c-single-frame-sub-view',multiViewElementName:'tv-c-multi-frame-sub-view'});return{Frame:Frame,FRAME_PERF_CLASS:FRAME_PERF_CLASS};});'use strict';tv.exportTo('tv.e.audits',function(){function mergeEvents(inEvents,mergeThreshold,mergeFunction,opt_startFunction,opt_endFunction){var startFunction=opt_startFunction;var endFunction=opt_endFunction;if(!startFunction)
+return{supported:true};},get textLabel(){return'Alerts';}});'use strict';tr.exportTo('tr.model',function(){var Statistics=tr.b.Statistics;var FRAME_PERF_CLASS={GOOD:'good',BAD:'bad',TERRIBLE:'terrible',NEUTRAL:'generic_work'};function Frame(associatedEvents,threadTimeRanges,opt_args){tr.model.Event.call(this);this.threadTimeRanges=threadTimeRanges;this.associatedEvents=associatedEvents;this.args=opt_args||{};this.title='Frame';this.start=Statistics.min(threadTimeRanges,function(x){return x.start;});this.end=Statistics.max(threadTimeRanges,function(x){return x.end;});this.totalDuration=Statistics.sum(threadTimeRanges,function(x){return x.end-x.start;});this.perfClass=FRAME_PERF_CLASS.NEUTRAL;};Frame.prototype={__proto__:tr.model.Event.prototype,set perfClass(perfClass){this.colorId=tr.b.ui.getColorIdForReservedName(perfClass);this.perfClass_=perfClass;},get perfClass(){return this.perfClass_;},shiftTimestampsForward:function(amount){this.start+=amount;this.end+=amount;for(var i=0;i<this.threadTimeRanges.length;i++){this.threadTimeRanges[i].start+=amount;this.threadTimeRanges[i].end+=amount;}},addBoundsToRange:function(range){range.addValue(this.start);range.addValue(this.end);}};tr.model.EventRegistry.register(Frame,{name:'frame',pluralName:'frames',singleViewElementName:'tr-c-a-single-frame-sub-view',multiViewElementName:'tr-c-a-multi-frame-sub-view'});return{Frame:Frame,FRAME_PERF_CLASS:FRAME_PERF_CLASS};});'use strict';tr.exportTo('tr.e.audits',function(){function mergeRanges(inRanges,mergeThreshold,mergeFunction){return mergeExplicitRanges(inRanges,mergeThreshold,mergeFunction,function(r){return r.min;},function(r){return r.max;});}
+function mergeExplicitRanges(inRanges,mergeThreshold,mergeFunction,opt_startFunction,opt_endFunction){var startFunction=opt_startFunction;var endFunction=opt_endFunction;if(!startFunction)
 startFunction=function(event){return event.start;};if(!endFunction)
-endFunction=function(event){return event.end;};var remainingEvents=inEvents.slice();remainingEvents.sort(function(x,y){return startFunction(x)-startFunction(y);});if(remainingEvents.length<=1){var merged=[];if(remainingEvents.length==1){merged.push(mergeFunction(remainingEvents));}
+endFunction=function(event){return event.end;};var remainingEvents=inRanges.slice();remainingEvents.sort(function(x,y){return startFunction(x)-startFunction(y);});if(remainingEvents.length<=1){var merged=[];if(remainingEvents.length==1){merged.push(mergeFunction(remainingEvents));}
 return merged;}
 var mergedEvents=[];var currentMergeBuffer=[];var rightEdge;function beginMerging(){currentMergeBuffer.push(remainingEvents[0]);remainingEvents.splice(0,1);rightEdge=endFunction(currentMergeBuffer[0]);}
 function flushCurrentMergeBuffer(){if(currentMergeBuffer.length==0)
@@ -4021,25 +4098,35 @@
 beginMerging();while(remainingEvents.length){var currentEvent=remainingEvents[0];var distanceFromRightEdge=startFunction(currentEvent)-rightEdge;if(distanceFromRightEdge<mergeThreshold){rightEdge=Math.max(rightEdge,endFunction(currentEvent));remainingEvents.splice(0,1);currentMergeBuffer.push(currentEvent);continue;}
 flushCurrentMergeBuffer();}
 flushCurrentMergeBuffer();return mergedEvents;}
-return{mergeEvents:mergeEvents};});'use strict';tv.exportTo('tv.e.audits',function(){var Frame=tv.c.trace_model.Frame;var Statistics=tv.b.Statistics;var UI_THREAD_DRAW_NAME='performTraversals';var RENDER_THREAD_DRAW_NAME='DrawFrame';var RENDER_THREAD_INDEP_DRAW_NAME='doFrame';var THREAD_SYNC_NAME='syncFrameState';function getSlicesForThreadTimeRanges(threadTimeRanges){var ret=[];threadTimeRanges.forEach(function(threadTimeRange){var slices=[];threadTimeRange.thread.sliceGroup.iterSlicesInTimeRange(function(slice){slices.push(slice);},threadTimeRange.start,threadTimeRange.end);ret.push.apply(ret,slices);});return ret;}
+function findEmptyRangesBetweenExplicitRanges(inRanges,opt_totalRange,opt_startFunction,opt_endFunction){var startFunction=opt_startFunction;if(!startFunction)
+startFunction=function(range){return range.start;};var endFunction=opt_endFunction;if(!endFunction)
+endFunction=function(range){return range.end;};var emptyRanges=[];if(!inRanges.length){if(opt_totalRange){emptyRanges.push(tr.b.Range.fromExplicitRange(startFunction(opt_totalRange),endFunction(opt_totalRange)));}
+return emptyRanges;}
+inRanges=inRanges.slice();inRanges.sort(function(x,y){return startFunction(x)-startFunction(y);});if(opt_totalRange&&(startFunction(opt_totalRange)<startFunction(inRanges[0]))){emptyRanges.push(tr.b.Range.fromExplicitRange(startFunction(opt_totalRange),startFunction(inRanges[0])));}
+inRanges.forEach(function(range,index){for(var otherIndex=0;otherIndex<inRanges.length;++otherIndex){if(index===otherIndex)
+continue;var other=inRanges[otherIndex];if(startFunction(other)>endFunction(range)){emptyRanges.push(tr.b.Range.fromExplicitRange(endFunction(range),startFunction(other)));return;}
+if(endFunction(other)>endFunction(range)){return;}}
+if(opt_totalRange&&(endFunction(range)<endFunction(opt_totalRange))){emptyRanges.push(tr.b.Range.fromExplicitRange(endFunction(range),endFunction(opt_totalRange)));}});return emptyRanges;}
+return{findEmptyRangesBetweenExplicitRanges:findEmptyRangesBetweenExplicitRanges,mergeExplicitRanges:mergeExplicitRanges,mergeRanges:mergeRanges};});'use strict';tr.exportTo('tr.e.audits',function(){var Frame=tr.model.Frame;var Statistics=tr.b.Statistics;var UI_THREAD_DRAW_NAMES={'performTraversals':true,'Choreographer#doFrame':true};var RENDER_THREAD_DRAW_NAME='DrawFrame';var RENDER_THREAD_INDEP_DRAW_NAME='doFrame';var THREAD_SYNC_NAME='syncFrameState';function getSlicesForThreadTimeRanges(threadTimeRanges){var ret=[];threadTimeRanges.forEach(function(threadTimeRange){var slices=[];threadTimeRange.thread.sliceGroup.iterSlicesInTimeRange(function(slice){slices.push(slice);},threadTimeRange.start,threadTimeRange.end);ret.push.apply(ret,slices);});return ret;}
 function makeFrame(threadTimeRanges,surfaceFlinger){var args={};if(surfaceFlinger&&surfaceFlinger.hasVsyncs){var start=Statistics.min(threadTimeRanges,function(threadTimeRanges){return threadTimeRanges.start;});args['deadline']=surfaceFlinger.getFrameDeadline(start);args['frameKickoff']=surfaceFlinger.getFrameKickoff(start);}
 var events=getSlicesForThreadTimeRanges(threadTimeRanges);return new Frame(events,threadTimeRanges,args);}
 function findOverlappingDrawFrame(renderThread,time){if(!renderThread)
 return undefined;var slices=renderThread.sliceGroup.slices;for(var i=0;i<slices.length;i++){var slice=slices[i];if(slice.title==RENDER_THREAD_DRAW_NAME&&slice.start<=time&&time<=slice.end){return slice;}}
 return undefined;}
 function getPreTraversalWorkRanges(uiThread){if(!uiThread)
-return[];var preFrameEvents=[];uiThread.sliceGroup.slices.forEach(function(slice){if(slice.title=='obtainView'||slice.title=='setupListItem'||slice.title=='deliverInputEvent')
+return[];var preFrameEvents=[];uiThread.sliceGroup.slices.forEach(function(slice){if(slice.title=='obtainView'||slice.title=='setupListItem'||slice.title=='deliverInputEvent'||slice.title=='RV Scroll')
 preFrameEvents.push(slice);});uiThread.asyncSliceGroup.slices.forEach(function(slice){if(slice.title=='deliverInputEvent')
-preFrameEvents.push(slice);});return tv.e.audits.mergeEvents(preFrameEvents,3,function(events){return{start:events[0].start,end:events[events.length-1].end};});}
-function getFrameStartTime(traversalStart,preTraversalWorkRanges){var preTraversalWorkRange=tv.b.findClosestIntervalInSortedIntervals(preTraversalWorkRanges,function(range){return range.start},function(range){return range.end},traversalStart,3);if(preTraversalWorkRange)
+preFrameEvents.push(slice);});return tr.e.audits.mergeExplicitRanges(preFrameEvents,3,function(events){return{start:events[0].start,end:events[events.length-1].end};});}
+function getFrameStartTime(traversalStart,preTraversalWorkRanges){var preTraversalWorkRange=tr.b.findClosestIntervalInSortedIntervals(preTraversalWorkRanges,function(range){return range.start},function(range){return range.end},traversalStart,3);if(preTraversalWorkRange)
 return preTraversalWorkRange.start;return traversalStart;}
 function getUiThreadDrivenFrames(app){if(!app.uiThread)
-return[];var preTraversalWorkRanges=getPreTraversalWorkRanges(app.uiThread);var frames=[];app.uiThread.sliceGroup.getSlicesOfName(UI_THREAD_DRAW_NAME).forEach(function(uiDrawSlice){var threadTimeRanges=[];var uiThreadTimeRange={thread:app.uiThread,start:getFrameStartTime(uiDrawSlice.start,preTraversalWorkRanges),end:uiDrawSlice.end};threadTimeRanges.push(uiThreadTimeRange);var rtDrawSlice=findOverlappingDrawFrame(app.renderThread,uiDrawSlice.end);if(rtDrawSlice){var rtSyncSlice=rtDrawSlice.findDescendentSlice(THREAD_SYNC_NAME);if(rtSyncSlice){uiThreadTimeRange.end=Math.min(uiThreadTimeRange.end,rtSyncSlice.start);}
+return[];var preTraversalWorkRanges=getPreTraversalWorkRanges(app.uiThread);var frames=[];app.uiThread.sliceGroup.slices.forEach(function(slice){if(!(slice.title in UI_THREAD_DRAW_NAMES)){return;}
+var threadTimeRanges=[];var uiThreadTimeRange={thread:app.uiThread,start:getFrameStartTime(slice.start,preTraversalWorkRanges),end:slice.end};threadTimeRanges.push(uiThreadTimeRange);var rtDrawSlice=findOverlappingDrawFrame(app.renderThread,slice.end);if(rtDrawSlice){var rtSyncSlice=rtDrawSlice.findDescendentSlice(THREAD_SYNC_NAME);if(rtSyncSlice){uiThreadTimeRange.end=Math.min(uiThreadTimeRange.end,rtSyncSlice.start);}
 threadTimeRanges.push({thread:app.renderThread,start:rtDrawSlice.start,end:rtDrawSlice.end});}
 frames.push(makeFrame(threadTimeRanges,app.surfaceFlinger));});return frames;}
 function getRenderThreadDrivenFrames(app){if(!app.renderThread)
 return[];var frames=[];app.renderThread.sliceGroup.getSlicesOfName(RENDER_THREAD_INDEP_DRAW_NAME).forEach(function(slice){var threadTimeRanges=[{thread:app.renderThread,start:slice.start,end:slice.end}];frames.push(makeFrame(threadTimeRanges,app.surfaceFlinger));});return frames;}
-function hasUiDraw(uiThread){var slices=uiThread.sliceGroup.slices;for(var i=0;i<slices.length;i++){var slice=slices[i];if(slice.title==UI_THREAD_DRAW_NAME){return uiThread;}}
+function hasUiDraw(uiThread){var slices=uiThread.sliceGroup.slices;for(var i=0;i<slices.length;i++){if(slices[i].title in UI_THREAD_DRAW_NAMES){return uiThread;}}
 return undefined;}
 function getInputSamples(process){var samples=undefined;for(var counterName in process.counters){if(/^android\.aq\:pending/.test(counterName)&&process.counters[counterName].numSeries==1){samples=process.counters[counterName].series[0].samples;break;}}
 if(!samples)
@@ -4053,7 +4140,7 @@
 AndroidApp.prototype={getFrames:function(){if(!this.frames_){var uiFrames=getUiThreadDrivenFrames(this);var rtFrames=getRenderThreadDrivenFrames(this);this.frames_=uiFrames.concat(rtFrames);this.frames_.sort(function(a,b){a.end-b.end});}
 return this.frames_;},getInputSamples:function(){if(!this.inputs_){this.inputs_=getInputSamples(this.process);}
 return this.inputs_;},getAnimationAsyncSlices:function(){if(!this.animations_){this.animations_=getAnimationAsyncSlices(this.uiThread);}
-return this.animations_;}};return{AndroidApp:AndroidApp};});'use strict';tv.exportTo('tv.e.audits',function(){var findLowIndexInSortedArray=tv.b.findLowIndexInSortedArray;var VSYNC_SF_NAME='android.VSYNC-sf';var VSYNC_APP_NAME='android.VSYNC-app';var VSYNC_FALLBACK_NAME='android.VSYNC';var TIMESTAMP_FUDGE_MS=0.01;function getVsyncTimestamps(process,counterName){var vsync=process.counters[counterName];if(!vsync)
+return this.animations_;}};return{AndroidApp:AndroidApp};});'use strict';tr.exportTo('tr.e.audits',function(){var findLowIndexInSortedArray=tr.b.findLowIndexInSortedArray;var VSYNC_SF_NAME='android.VSYNC-sf';var VSYNC_APP_NAME='android.VSYNC-app';var VSYNC_FALLBACK_NAME='android.VSYNC';var TIMESTAMP_FUDGE_MS=0.01;function getVsyncTimestamps(process,counterName){var vsync=process.counters[counterName];if(!vsync)
 vsync=process.counters[VSYNC_FALLBACK_NAME];if(vsync&&vsync.numSeries==1&&vsync.numSamples>1)
 return vsync.series[0].timestamps;return undefined;}
 function AndroidSurfaceFlinger(process,thread){this.process=process;this.thread=thread;this.appVsync_=undefined;this.sfVsync_=undefined;this.appVsyncTimestamps_=getVsyncTimestamps(process,VSYNC_APP_NAME);this.sfVsyncTimestamps_=getVsyncTimestamps(process,VSYNC_SF_NAME);};AndroidSurfaceFlinger.createForProcessIfPossible=function(process){var mainThread=process.getThread(process.pid);if(mainThread&&mainThread.name&&/surfaceflinger/.test(mainThread.name))
@@ -4062,19 +4149,19 @@
 throw new Error('cannot query vsync info without vsyncs');var firstGreaterIndex=findLowIndexInSortedArray(this.appVsyncTimestamps_,function(x){return x;},timestamp+TIMESTAMP_FUDGE_MS);if(firstGreaterIndex<1)
 return undefined;return this.appVsyncTimestamps_[firstGreaterIndex-1];},getFrameDeadline:function(timestamp){if(!this.hasVsyncs)
 throw new Error('cannot query vsync info without vsyncs');var firstGreaterIndex=findLowIndexInSortedArray(this.sfVsyncTimestamps_,function(x){return x;},timestamp+TIMESTAMP_FUDGE_MS);if(firstGreaterIndex>=this.sfVsyncTimestamps_.length)
-return undefined;return this.sfVsyncTimestamps_[firstGreaterIndex];}};return{AndroidSurfaceFlinger:AndroidSurfaceFlinger};});'use strict';tv.exportTo('tv.e.audits',function(){var AndroidApp=tv.e.audits.AndroidApp;var AndroidSurfaceFlinger=tv.e.audits.AndroidSurfaceFlinger;var IMPORTANT_SURFACE_FLINGER_SLICES={'doComposition':true,'updateTexImage':true,'postFramebuffer':true};var IMPORTANT_UI_THREAD_SLICES={'performTraversals':true,'deliverInputEvent':true};var IMPORTANT_RENDER_THREAD_SLICES={'doFrame':true};function iterateImportantThreadSlices(thread,important,callback){if(!thread)
+return undefined;return this.sfVsyncTimestamps_[firstGreaterIndex];}};return{AndroidSurfaceFlinger:AndroidSurfaceFlinger};});'use strict';tr.exportTo('tr.e.audits',function(){var AndroidApp=tr.e.audits.AndroidApp;var AndroidSurfaceFlinger=tr.e.audits.AndroidSurfaceFlinger;var IMPORTANT_SURFACE_FLINGER_SLICES={'doComposition':true,'updateTexImage':true,'postFramebuffer':true};var IMPORTANT_UI_THREAD_SLICES={'Choreographer#doFrame':true,'performTraversals':true,'deliverInputEvent':true};var IMPORTANT_RENDER_THREAD_SLICES={'doFrame':true};function iterateImportantThreadSlices(thread,important,callback){if(!thread)
 return;thread.sliceGroup.slices.forEach(function(slice){if(slice.title in important)
 callback(slice);});}
 function AndroidModelHelper(model){this.model=model;this.apps=[];this.surfaceFlinger=undefined;var processes=model.getAllProcesses();for(var i=0;i<processes.length&&!this.surfaceFlinger;i++){this.surfaceFlinger=AndroidSurfaceFlinger.createForProcessIfPossible(processes[i]);}
 model.getAllProcesses().forEach(function(process){var app=AndroidApp.createForProcessIfPossible(process,this.surfaceFlinger);if(app)
 this.apps.push(app);},this);};AndroidModelHelper.prototype={iterateImportantSlices:function(callback){if(this.surfaceFlinger){iterateImportantThreadSlices(this.surfaceFlinger.thread,IMPORTANT_SURFACE_FLINGER_SLICES,callback);}
-this.apps.forEach(function(app){iterateImportantThreadSlices(app.uiThread,IMPORTANT_UI_THREAD_SLICES,callback);iterateImportantThreadSlices(app.renderThread,IMPORTANT_RENDER_THREAD_SLICES,callback);});}};return{AndroidModelHelper:AndroidModelHelper};});'use strict';tv.exportTo('tv.e.audits',function(){var SCHEDULING_STATE=tv.c.trace_model.SCHEDULING_STATE;var Auditor=tv.c.Auditor;var AndroidModelHelper=tv.e.audits.AndroidModelHelper;var Statistics=tv.b.Statistics;var FRAME_PERF_CLASS=tv.c.trace_model.FRAME_PERF_CLASS;var InteractionRecord=tv.c.trace_model.InteractionRecord;var Alert=tv.c.trace_model.Alert;var EventInfo=tv.c.trace_model.EventInfo;var TimeDuration=tv.b.TimeDuration;var EXPECTED_FRAME_TIME_MS=16.67;function getStart(e){return e.start;}
+this.apps.forEach(function(app){iterateImportantThreadSlices(app.uiThread,IMPORTANT_UI_THREAD_SLICES,callback);iterateImportantThreadSlices(app.renderThread,IMPORTANT_RENDER_THREAD_SLICES,callback);});}};return{AndroidModelHelper:AndroidModelHelper};});'use strict';tr.exportTo('tr.e.audits',function(){var SCHEDULING_STATE=tr.model.SCHEDULING_STATE;var Auditor=tr.c.Auditor;var AndroidModelHelper=tr.e.audits.AndroidModelHelper;var Statistics=tr.b.Statistics;var FRAME_PERF_CLASS=tr.model.FRAME_PERF_CLASS;var InteractionRecord=tr.model.InteractionRecord;var Alert=tr.model.Alert;var EventInfo=tr.model.EventInfo;var TimeDuration=tr.b.units.TimeDuration;var EXPECTED_FRAME_TIME_MS=16.67;function getStart(e){return e.start;}
 function getDuration(e){return e.duration;}
 function getCpuDuration(e){return(e.cpuDuration!==undefined)?e.cpuDuration:e.duration;}
 function frameIsActivityStart(frame){for(var i=0;i<frame.associatedEvents.length;i++){if(frame.associatedEvents[i].title=='activityStart')
 return true;}
 return false;}
-var MAX_TIME_UNSCHEDULED=3.0;var MAX_TIME_BLOCKING_IO=5.0;var Auditor=tv.c.Auditor;var AndroidModelHelper=tv.e.audits.AndroidModelHelper;function frameMissedDeadline(frame){return frame.args['deadline']&&frame.args['deadline']<frame.end;}
+var Auditor=tr.c.Auditor;var AndroidModelHelper=tr.e.audits.AndroidModelHelper;function frameMissedDeadline(frame){return frame.args['deadline']&&frame.args['deadline']<frame.end;}
 function DocLinkBuilder(){this.docLinks=[];}
 DocLinkBuilder.prototype={addAppVideo:function(name,videoId){this.docLinks.push({label:'Video Link',textContent:('Android Performance Patterns: '+name),href:'https://www.youtube.com/watch?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE&v='+videoId});return this;},addDacRef:function(name,link){this.docLinks.push({label:'Doc Link',textContent:(name+' documentation'),href:'https://developer.android.com/reference/'+link});return this;},build:function(){return this.docLinks;}};function AndroidAuditor(model){this.model=model;var helper=new AndroidModelHelper(model);if(helper.apps.length||helper.surfaceFlinger)
 this.helper=helper;};AndroidAuditor.viewAlphaAlertInfo_=new EventInfo('Inefficient View alpha usage','Setting an alpha between 0 and 1 has significant performance costs, if one of the fast alpha paths is not used.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('View#setAlpha()','android/view/View.html#setAlpha(float)').build());AndroidAuditor.saveLayerAlertInfo_=new EventInfo('Expensive rendering with Canvas#saveLayer()','Canvas#saveLayer() incurs extremely high rendering cost. They disrupt the rendering pipeline when drawn, forcing a flush of drawing content. Instead use View hardware layers, or static Bitmaps. This enables the offscreen buffers to be reused in between frames, and avoids the disruptive render target switch.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('Canvas#saveLayerAlpha()','android/graphics/Canvas.html#saveLayerAlpha(android.graphics.RectF, int, int)').build());AndroidAuditor.getSaveLayerAlerts_=function(frame){var badAlphaRegEx=/^(.+) alpha caused (unclipped )?saveLayer (\d+)x(\d+)$/;var saveLayerRegEx=/^(unclipped )?saveLayer (\d+)x(\d+)$/;var ret=[];var events=[];frame.associatedEvents.forEach(function(slice){var match=badAlphaRegEx.exec(slice.title);if(match){var args={'view name':match[1],width:parseInt(match[3]),height:parseInt(match[4])};ret.push(new Alert(AndroidAuditor.viewAlphaAlertInfo_,slice.start,[slice],args));}else if(saveLayerRegEx.test(slice.title))
@@ -4084,7 +4171,7 @@
 AndroidAuditor.uploadAlertInfo_=new EventInfo('Expensive Bitmap uploads','Bitmaps that have been modified / newly drawn must be uploaded to the GPU. Since this is expensive if the total number of pixels uploaded is large, reduce the amount of Bitmap churn in this animation/context, per frame.');AndroidAuditor.getUploadAlert_=function(frame){var uploadRegEx=/^Upload (\d+)x(\d+) Texture$/;var events=[];var start=Number.POSITIVE_INFINITY;var duration=0;var pixelsUploaded=0;frame.associatedEvents.forEach(function(event){var match=uploadRegEx.exec(event.title);if(match){events.push(event);start=Math.min(start,event.start);duration+=event.duration;pixelsUploaded+=parseInt(match[1])*parseInt(match[2]);}});if(events.length==0||duration<3)
 return undefined;var mPixels=(pixelsUploaded/1000000).toFixed(2)+' million';var args={'Pixels uploaded':mPixels,'Time spent':new TimeDuration(duration)};events.push(frame);return new Alert(AndroidAuditor.uploadAlertInfo_,start,events,args);}
 AndroidAuditor.ListViewInflateAlertInfo_=new EventInfo('Inflation during ListView recycling','ListView item recycling involved inflating views. Ensure your Adapter#getView() recycles the incoming View, instead of constructing a new one.');AndroidAuditor.ListViewBindAlertInfo_=new EventInfo('Inefficient ListView recycling/rebinding','ListView recycling taking too much time per frame. Ensure your Adapter#getView() binds data efficiently.');AndroidAuditor.getListViewAlert_=function(frame){var events=frame.associatedEvents.filter(function(event){return event.title=='obtainView'||event.title=='setupListItem';});var duration=Statistics.sum(events,getCpuDuration);if(events.length==0||duration<3)
-return undefined;var hasInflation=false;for(var i=0;i<events.length;i++){if(events[i]instanceof tv.c.trace_model.Slice&&events[i].findDescendentSlice('inflate')){hasInflation=true;break;}}
+return undefined;var hasInflation=false;for(var i=0;i<events.length;i++){if(events[i]instanceof tr.model.Slice&&events[i].findDescendentSlice('inflate')){hasInflation=true;break;}}
 var start=Statistics.min(events,getStart);var args={'Time spent':new TimeDuration(duration)};args['ListView items '+(hasInflation?'inflated':'rebound')]=events.length/2;var eventInfo=hasInflation?AndroidAuditor.ListViewInflateAlertInfo_:AndroidAuditor.ListViewBindAlertInfo_;events.push(frame);return new Alert(eventInfo,start,events,args);}
 AndroidAuditor.measureLayoutAlertInfo_=new EventInfo('Expensive measure/layout pass','Measure/Layout took a significant time, contributing to jank. Avoid triggering layout during animations.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').build());AndroidAuditor.getMeasureLayoutAlert_=function(frame){var events=frame.associatedEvents.filter(function(event){return event.title=='measure'||event.title=='layout';});var duration=Statistics.sum(events,getCpuDuration);if(events.length==0||duration<3)
 return undefined;var start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.measureLayoutAlertInfo_,start,events,{'Time spent':new TimeDuration(duration)});}
@@ -4093,9 +4180,9 @@
 return undefined;return new Alert(AndroidAuditor.viewDrawAlertInfo_,slice.start,[slice,frame],{'Time spent':new TimeDuration(getCpuDuration(slice))});}
 AndroidAuditor.blockingGcAlertInfo_=new EventInfo('Blocking Garbage Collection','Blocking GCs are caused by object churn, and made worse by having large numbers of objects in the heap. Avoid allocating objects during animations/scrolling, and recycle Bitmaps to avoid triggering garbage collection.',new DocLinkBuilder().addAppVideo('Garbage Collection in Android','pzfzz50W5Uo').addAppVideo('Avoiding Allocations in onDraw()','HAK5acHQ53E').build());AndroidAuditor.getBlockingGcAlert_=function(frame){var events=frame.associatedEvents.filter(function(event){return event.title=='DVM Suspend'||event.title=='GC: Wait For Concurrent';});var blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<3)
 return undefined;var start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.blockingGcAlertInfo_,start,events,{'Blocked duration':new TimeDuration(blockedDuration)});};AndroidAuditor.lockContentionAlertInfo_=new EventInfo('Lock contention','UI thread lock contention is caused when another thread holds a lock that the UI thread is trying to use. UI thread progress is blocked until the lock is released. Inspect locking done within the UI thread, and ensure critical sections are short.');AndroidAuditor.getLockContentionAlert_=function(frame){var events=frame.associatedEvents.filter(function(event){return/^Lock Contention on /.test(event.title);});var blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<1)
-return undefined;var start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.lockContentionAlertInfo_,start,events,{'Blocked duration':new TimeDuration(blockedDuration)});};AndroidAuditor.schedulingAlertInfo_=new EventInfo('Scheduling delay','Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should with a priority number of 130 or higher in the scheduling section under the Kernel process.');AndroidAuditor.getSchedulingAlert_=function(frame){var totalDuration=0;var totalStats={};frame.threadTimeRanges.forEach(function(ttr){var stats=ttr.thread.getSchedulingStatsForRange(ttr.start,ttr.end);tv.b.iterItems(stats,function(key,value){if(!(key in totalStats))
+return undefined;var start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.lockContentionAlertInfo_,start,events,{'Blocked duration':new TimeDuration(blockedDuration)});};AndroidAuditor.schedulingAlertInfo_=new EventInfo('Scheduling delay','Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.');AndroidAuditor.getSchedulingAlert_=function(frame){var totalDuration=0;var totalStats={};frame.threadTimeRanges.forEach(function(ttr){var stats=ttr.thread.getSchedulingStatsForRange(ttr.start,ttr.end);tr.b.iterItems(stats,function(key,value){if(!(key in totalStats))
 totalStats[key]=0;totalStats[key]+=value;totalDuration+=value;});});if(!(SCHEDULING_STATE.RUNNING in totalStats)||totalDuration==0||totalDuration-totalStats[SCHEDULING_STATE.RUNNING]<3)
-return;var args={};tv.b.iterItems(totalStats,function(key,value){if(key===SCHEDULING_STATE.RUNNABLE)
+return;var args={};tr.b.iterItems(totalStats,function(key,value){if(key===SCHEDULING_STATE.RUNNABLE)
 key='Not scheduled, but runnable';else if(key===SCHEDULING_STATE.UNINTR_SLEEP)
 key='Blocking I/O delay';args[key]=new TimeDuration(value);});return new Alert(AndroidAuditor.schedulingAlertInfo_,frame.start,[frame],args);};AndroidAuditor.prototype={__proto__:Auditor.prototype,renameAndSort_:function(){this.model.kernel.important=false;this.model.getAllProcesses().forEach(function(process){if(this.helper.surfaceFlinger&&process==this.helper.surfaceFlinger.process){if(!process.name)
 process.name='SurfaceFlinger';process.sortIndex=Number.NEGATIVE_INFINITY;process.important=false;return;}
@@ -4120,9 +4207,11 @@
 alerts.push(alert);var alert=AndroidAuditor.getBlockingGcAlert_(frame);if(alert)
 alerts.push(alert);var alert=AndroidAuditor.getLockContentionAlert_(frame);if(alert)
 alerts.push(alert);var alert=AndroidAuditor.getSchedulingAlert_(frame);if(alert)
-alerts.push(alert);});},this);this.addRenderingInteractionRecords();this.addInputInteractionRecords();},addRenderingInteractionRecords:function(){var events=[];this.helper.apps.forEach(function(app){events.push.apply(events,app.getAnimationAsyncSlices());events.push.apply(events,app.getFrames());});var mergerFunction=function(events){var ir=new InteractionRecord('Rendering',tv.b.ui.getColorIdForGeneralPurposeString('mt_rendering'),events[0].start,events[events.length-1].end-events[0].start);this.model.addInteractionRecord(ir);}.bind(this);tv.e.audits.mergeEvents(events,30,mergerFunction);},addInputInteractionRecords:function(){var inputSamples=[];this.helper.apps.forEach(function(app){inputSamples.push.apply(inputSamples,app.getInputSamples());});var mergerFunction=function(events){var ir=new InteractionRecord('Input',tv.b.ui.getColorIdForGeneralPurposeString('mt_input'),events[0].timestamp,events[events.length-1].timestamp-events[0].timestamp);this.model.addInteractionRecord(ir);}.bind(this);var timestampFunction=function(x){return x.timestamp;};tv.e.audits.mergeEvents(inputSamples,30,mergerFunction,timestampFunction,timestampFunction);}};Auditor.register(AndroidAuditor);function AppAnnotator(){this.titleInfoLookup={};this.titleParentLookup={};this.build_();}
-AppAnnotator.prototype={build_:function(){var registerEventInfo=function(dict){this.titleInfoLookup[dict.title]=new EventInfo(dict.title,dict.description,dict.docLinks);if(dict.parent)
-this.titleParentLookup[dict.title]=dict.parent;}.bind(this);registerEventInfo({title:'inflate',description:'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'});registerEventInfo({title:'obtainView',description:'Adapter#getView() called to bind content to a recycled View that is being presented.'});registerEventInfo({title:'setupListItem',description:'Attached a newly-bound, recycled View to its parent ListView.'});registerEventInfo({title:'setupGridItem',description:'Attached a newly-bound, recycled View to its parent GridView.'});registerEventInfo({title:'performTraversals',description:'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'});registerEventInfo({title:'measure',parent:'performTraversals',docLinks:{'View#layout documentation':'https://developer.android.com/reference/android/view/View.html#Layout'},description:'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'});registerEventInfo({title:'layout',parent:'performTraversals',docLinks:{'View#layout documentation':'https://developer.android.com/reference/android/view/View.html#Layout'},description:'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'});registerEventInfo({title:'draw',parent:'performTraversals',description:'Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.'});var recordString='Every invalidated View\'s drawing commands are recorded. Each will have View#draw() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.';registerEventInfo({title:'getDisplayList',parent:'draw',description:recordString});registerEventInfo({title:'Record View#draw()',parent:'draw',description:recordString});registerEventInfo({title:'drawDisplayList',parent:'draw',description:'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'DrawFrame',description:'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'doFrame',description:'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'});registerEventInfo({title:'syncFrameState',description:'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'});registerEventInfo({title:'flush drawing commands',description:'Issuing the now complete drawing commands to the GPU.'});registerEventInfo({title:'eglSwapBuffers',description:'Complete GPU rendering of the frame.'});registerEventInfo({title:'RV Scroll',description:'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'});registerEventInfo({title:'RV OnLayout',description:'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'});registerEventInfo({title:'RV FullInvalidate',description:'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'});registerEventInfo({title:'RV PartialInvalidate',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV OnBindView',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV CreateView',description:'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'});registerEventInfo({title:'eglSwapBuffers',description:'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'});},applyEventInfosRecursive_:function(parentNames,slice){if(slice.title in this.titleInfoLookup){var expectedParentName=this.titleParentLookup[slice.title];if(!expectedParentName||expectedParentName in parentNames)
+alerts.push(alert);});},this);this.addRenderingInteractionRecords();this.addInputInteractionRecords();},addRenderingInteractionRecords:function(){var events=[];this.helper.apps.forEach(function(app){events.push.apply(events,app.getAnimationAsyncSlices());events.push.apply(events,app.getFrames());});var mergerFunction=function(events){var ir=new InteractionRecord('Rendering',tr.b.ui.getColorIdForGeneralPurposeString('mt_rendering'),events[0].start,events[events.length-1].end-events[0].start);this.model.addInteractionRecord(ir);}.bind(this);tr.e.audits.mergeExplicitRanges(events,30,mergerFunction);},addInputInteractionRecords:function(){var inputSamples=[];this.helper.apps.forEach(function(app){inputSamples.push.apply(inputSamples,app.getInputSamples());});var mergerFunction=function(events){var ir=new InteractionRecord('Input',tr.b.ui.getColorIdForGeneralPurposeString('mt_input'),events[0].timestamp,events[events.length-1].timestamp-events[0].timestamp);this.model.addInteractionRecord(ir);}.bind(this);var timestampFunction=function(x){return x.timestamp;};tr.e.audits.mergeExplicitRanges(inputSamples,30,mergerFunction,timestampFunction,timestampFunction);}};Auditor.register(AndroidAuditor);function AppAnnotator(){this.titleInfoLookup={};this.titleParentLookup={};this.build_();}
+AppAnnotator.prototype={build_:function(){var registerEventInfo=function(dict){this.titleInfoLookup[dict.title]=new EventInfo(dict.title,dict.description,dict.docLinks);if(dict.parents)
+this.titleParentLookup[dict.title]=dict.parents;}.bind(this);registerEventInfo({title:'inflate',description:'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'});registerEventInfo({title:'obtainView',description:'Adapter#getView() called to bind content to a recycled View that is being presented.'});registerEventInfo({title:'setupListItem',description:'Attached a newly-bound, recycled View to its parent ListView.'});registerEventInfo({title:'setupGridItem',description:'Attached a newly-bound, recycled View to its parent GridView.'});var choreographerLinks=new DocLinkBuilder().addDacRef('Choreographer','android/view/Choreographer.html').build();registerEventInfo({title:'Choreographer#doFrame',docLinks:choreographerLinks,description:'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'});registerEventInfo({title:'input',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'});registerEventInfo({title:'animation',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'});registerEventInfo({title:'traversals',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'});var traversalParents=['Choreographer#doFrame','performTraversals'];var layoutLinks=new DocLinkBuilder().addDacRef('View#Layout','android/view/View.html#Layout').build();registerEventInfo({title:'performTraversals',description:'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'});registerEventInfo({title:'measure',parents:traversalParents,docLinks:layoutLinks,description:'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'});registerEventInfo({title:'layout',parents:traversalParents,docLinks:layoutLinks,description:'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'});var drawString='Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.';registerEventInfo({title:'draw',parents:traversalParents,description:drawString});var recordString='Every invalidated View\'s drawing commands are recorded. Each will have View#draw() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.';registerEventInfo({title:'getDisplayList',parents:['draw'],description:recordString});registerEventInfo({title:'Record View#draw()',parents:['draw'],description:recordString});registerEventInfo({title:'drawDisplayList',parents:['draw'],description:'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'});registerEventInfo({title:'DrawFrame',description:'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'doFrame',description:'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'});registerEventInfo({title:'syncFrameState',description:'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'});registerEventInfo({title:'flush drawing commands',description:'Issuing the now complete drawing commands to the GPU.'});registerEventInfo({title:'eglSwapBuffers',description:'Complete GPU rendering of the frame.'});registerEventInfo({title:'RV Scroll',description:'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'});registerEventInfo({title:'RV OnLayout',description:'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'});registerEventInfo({title:'RV FullInvalidate',description:'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'});registerEventInfo({title:'RV PartialInvalidate',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV OnBindView',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV CreateView',description:'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'});registerEventInfo({title:'eglSwapBuffers',description:'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'});},applyEventInfosRecursive_:function(parentNames,slice){var checkExpectedParentNames=function(expectedParentNames){if(!expectedParentNames)
+return true;return expectedParentNames.some(function(name){return name in parentNames;});}
+if(slice.title in this.titleInfoLookup){if(checkExpectedParentNames(this.titleParentLookup[slice.title]))
 slice.info=this.titleInfoLookup[slice.title];}
 if(slice.subSlices.length>0){if(!(slice.title in parentNames))
 parentNames[slice.title]=0;parentNames[slice.title]++;slice.subSlices.forEach(function(subSlice){this.applyEventInfosRecursive_(parentNames,subSlice);},this);parentNames[slice.title]--;if(parentNames[slice.title]==0)
diff --git a/trace-viewer/BUILD.gn b/trace-viewer/BUILD.gn
index 2f798f3..ba379e3 100644
--- a/trace-viewer/BUILD.gn
+++ b/trace-viewer/BUILD.gn
@@ -1,398 +1,11 @@
- # Copyright 2014 The Chromium Authors. All rights reserved.
+# Copyright 2014 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.
 
-tracing_css_files = [
-  "trace_viewer/base/ui/common.css",
-  "trace_viewer/base/ui/drag_handle.css",
-  "trace_viewer/base/ui/line_chart.css",
-  "trace_viewer/base/ui/list_view.css",
-  "trace_viewer/base/ui/mouse_mode_selector.css",
-  "trace_viewer/base/ui/pie_chart.css",
-  "trace_viewer/base/ui/sortable_table.css",
-  "trace_viewer/base/ui/sunburst_chart.css",
-  "trace_viewer/base/ui/tool_button.css",
-  "trace_viewer/core/analysis/analysis_results.css",
-  "trace_viewer/core/timeline_track_view.css",
-  "trace_viewer/core/timeline_view.css",
-  "trace_viewer/core/tracks/drawing_container.css",
-  "trace_viewer/core/tracks/heading_track.css",
-  "trace_viewer/core/tracks/object_instance_track.css",
-  "trace_viewer/core/tracks/process_track_base.css",
-  "trace_viewer/core/tracks/rect_track.css",
-  "trace_viewer/core/tracks/ruler_track.css",
-  "trace_viewer/core/tracks/spacing_track.css",
-  "trace_viewer/core/tracks/thread_track.css",
-  "trace_viewer/core/tracks/track.css",
-  "trace_viewer/extras/about_tracing/common.css",
-  "trace_viewer/extras/chrome/cc/display_item_view.css",
-  "trace_viewer/extras/chrome/cc/layer_picker.css",
-  "trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.css",
-  "trace_viewer/extras/chrome/cc/layer_view.css",
-  "trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.css",
-  "trace_viewer/extras/chrome/cc/picture_ops_chart_view.css",
-  "trace_viewer/extras/chrome/cc/picture_ops_list_view.css",
-  "trace_viewer/extras/chrome/cc/picture_view.css",
-  "trace_viewer/extras/chrome/gpu/state_view.css",
-  "trace_viewer/extras/system_stats/system_stats_instance_track.css",
-  "trace_viewer/extras/system_stats/system_stats_snapshot_view.css",
-  "trace_viewer/extras/tcmalloc/heap_instance_track.css",
-  "trace_viewer/extras/tcmalloc/tcmalloc_instance_view.css",
-  "trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.css",
-]
-tracing_js_html_files = [
-  "trace_viewer/base/base.html",
-  "trace_viewer/base/base64.html",
-  "trace_viewer/base/bbox2.html",
-  "trace_viewer/base/category_util.html",
-  "trace_viewer/base/color.html",
-  "trace_viewer/base/event_target.html",
-  "trace_viewer/base/events.html",
-  "trace_viewer/base/extension_registry.html",
-  "trace_viewer/base/extension_registry_base.html",
-  "trace_viewer/base/extension_registry_basic.html",
-  "trace_viewer/base/extension_registry_type_based.html",
-  "trace_viewer/base/gl_matrix.html",
-  "trace_viewer/base/guid.html",
-  "trace_viewer/base/interval_tree.html",
-  "trace_viewer/base/iteration_helpers.html",
-  "trace_viewer/base/key_event_manager.html",
-  "trace_viewer/base/polymer_utils.html",
-  "trace_viewer/base/properties.html",
-  "trace_viewer/base/quad.html",
-  "trace_viewer/base/raf.html",
-  "trace_viewer/base/range.html",
-  "trace_viewer/base/rect.html",
-  "trace_viewer/base/settings.html",
-  "trace_viewer/base/sorted_array_utils.html",
-  "trace_viewer/base/statistics.html",
-  "trace_viewer/base/task.html",
-  "trace_viewer/base/time.html",
-  "trace_viewer/base/ui.html",
-  "trace_viewer/base/ui/animation.html",
-  "trace_viewer/base/ui/animation_controller.html",
-  "trace_viewer/base/ui/camera.html",
-  "trace_viewer/base/ui/chart_base.html",
-  "trace_viewer/base/ui/color_legend.html",
-  "trace_viewer/base/ui/color_scheme.html",
-  "trace_viewer/base/ui/color_utils.html",
-  "trace_viewer/base/ui/container_that_decorates_its_children.html",
-  "trace_viewer/base/ui/d3.html",
-  "trace_viewer/base/ui/dom_helpers.html",
-  "trace_viewer/base/ui/drag_handle.html",
-  "trace_viewer/base/ui/dropdown.html",
-  "trace_viewer/base/ui/info_bar.html",
-  "trace_viewer/base/ui/info_bar_group.html",
-  "trace_viewer/base/ui/line_chart.html",
-  "trace_viewer/base/ui/list_view.html",
-  "trace_viewer/base/ui/mouse_mode_selector.html",
-  "trace_viewer/base/ui/mouse_tracker.html",
-  "trace_viewer/base/ui/overlay.html",
-  "trace_viewer/base/ui/pie_chart.html",
-  "trace_viewer/base/ui/quad_stack_view.html",
-  "trace_viewer/base/ui/sortable_table.html",
-  "trace_viewer/base/ui/sunburst_chart.html",
-  "trace_viewer/base/utils.html",
-  "trace_viewer/core/analysis/alert_sub_view.html",
-  "trace_viewer/core/analysis/analysis_link.html",
-  "trace_viewer/core/analysis/analysis_results.html",
-  "trace_viewer/core/analysis/analysis_sub_view.html",
-  "trace_viewer/core/analysis/analysis_view.html",
-  "trace_viewer/core/analysis/counter_sample_sub_view.html",
-  "trace_viewer/core/analysis/flow_classifier.html",
-  "trace_viewer/core/analysis/generic_object_view.html",
-  "trace_viewer/core/analysis/memory_dump_allocator_details_pane.html",
-  "trace_viewer/core/analysis/memory_dump_overview_pane.html",
-  "trace_viewer/core/analysis/memory_dump_sub_view_util.html",
-  "trace_viewer/core/analysis/memory_dump_view.html",
-  "trace_viewer/core/analysis/memory_dump_vm_regions_details_pane.html",
-  "trace_viewer/core/analysis/multi_async_slice_sub_view.html",
-  "trace_viewer/core/analysis/multi_cpu_slice_sub_view.html",
-  "trace_viewer/core/analysis/multi_event_details_table.html",
-  "trace_viewer/core/analysis/multi_event_sub_view.html",
-  "trace_viewer/core/analysis/multi_event_summary.html",
-  "trace_viewer/core/analysis/multi_event_summary_table.html",
-  "trace_viewer/core/analysis/multi_flow_event_sub_view.html",
-  "trace_viewer/core/analysis/multi_frame_sub_view.html",
-  "trace_viewer/core/analysis/multi_global_memory_dump_sub_view.html",
-  "trace_viewer/core/analysis/multi_instant_event_sub_view.html",
-  "trace_viewer/core/analysis/multi_interaction_record_sub_view.html",
-  "trace_viewer/core/analysis/multi_object_sub_view.html",
-  "trace_viewer/core/analysis/multi_process_memory_dump_sub_view.html",
-  "trace_viewer/core/analysis/multi_sample_sub_view.html",
-  "trace_viewer/core/analysis/multi_thread_slice_sub_view.html",
-  "trace_viewer/core/analysis/multi_thread_time_slice_sub_view.html",
-  "trace_viewer/core/analysis/object_instance_view.html",
-  "trace_viewer/core/analysis/object_snapshot_view.html",
-  "trace_viewer/core/analysis/related_flows.html",
-  "trace_viewer/core/analysis/selection_summary_table.html",
-  "trace_viewer/core/analysis/single_async_slice_sub_view.html",
-  "trace_viewer/core/analysis/single_cpu_slice_sub_view.html",
-  "trace_viewer/core/analysis/single_event_sub_view.html",
-  "trace_viewer/core/analysis/single_flow_event_sub_view.html",
-  "trace_viewer/core/analysis/single_frame_sub_view.html",
-  "trace_viewer/core/analysis/single_global_memory_dump_sub_view.html",
-  "trace_viewer/core/analysis/single_instant_event_sub_view.html",
-  "trace_viewer/core/analysis/single_interaction_record_sub_view.html",
-  "trace_viewer/core/analysis/single_object_instance_sub_view.html",
-  "trace_viewer/core/analysis/single_object_snapshot_sub_view.html",
-  "trace_viewer/core/analysis/single_process_memory_dump_sub_view.html",
-  "trace_viewer/core/analysis/single_sample_sub_view.html",
-  "trace_viewer/core/analysis/single_thread_slice_sub_view.html",
-  "trace_viewer/core/analysis/single_thread_time_slice_sub_view.html",
-  "trace_viewer/core/analysis/size_span.html",
-  "trace_viewer/core/analysis/stack_frame.html",
-  "trace_viewer/core/analysis/tab_view.html",
-  "trace_viewer/core/analysis/table_builder.html",
-  "trace_viewer/core/analysis/time_span.html",
-  "trace_viewer/core/analysis/time_stamp.html",
-  "trace_viewer/core/analysis/toggle_container.html",
-  "trace_viewer/core/analysis/util.html",
-  "trace_viewer/core/auditor.html",
-  "trace_viewer/core/brushing_state.html",
-  "trace_viewer/core/constants.html",
-  "trace_viewer/core/draw_helpers.html",
-  "trace_viewer/core/elided_cache.html",
-  "trace_viewer/core/event_presenter.html",
-  "trace_viewer/core/fast_rect_renderer.html",
-  "trace_viewer/core/favicons.html",
-  "trace_viewer/core/filter.html",
-  "trace_viewer/core/find_control.html",
-  "trace_viewer/core/find_controller.html",
-  "trace_viewer/core/importer/empty_importer.html",
-  "trace_viewer/core/importer/importer.html",
-  "trace_viewer/core/importer/simple_line_reader.html",
-  "trace_viewer/core/location.html",
-  "trace_viewer/core/scripting_control.html",
-  "trace_viewer/core/scripting_controller.html",
-  "trace_viewer/core/scripting_object.html",
-  "trace_viewer/core/selection.html",
-  "trace_viewer/core/selection_controller.html",
-  "trace_viewer/core/side_panel/side_panel.html",
-  "trace_viewer/core/side_panel/side_panel_container.html",
-  "trace_viewer/core/timeline_display_transform.html",
-  "trace_viewer/core/timeline_display_transform_animations.html",
-  "trace_viewer/core/timeline_interest_range.html",
-  "trace_viewer/core/timeline_track_view.html",
-  "trace_viewer/core/timeline_view.html",
-  "trace_viewer/core/timeline_viewport.html",
-  "trace_viewer/core/timing_tool.html",
-  "trace_viewer/core/trace_model/alert.html",
-  "trace_viewer/core/trace_model/annotation.html",
-  "trace_viewer/core/trace_model/async_slice.html",
-  "trace_viewer/core/trace_model/async_slice_group.html",
-  "trace_viewer/core/trace_model/attribute.html",
-  "trace_viewer/core/trace_model/comment_box_annotation.html",
-  "trace_viewer/core/trace_model/container_memory_dump.html",
-  "trace_viewer/core/trace_model/counter.html",
-  "trace_viewer/core/trace_model/counter_sample.html",
-  "trace_viewer/core/trace_model/counter_series.html",
-  "trace_viewer/core/trace_model/cpu.html",
-  "trace_viewer/core/trace_model/cpu_slice.html",
-  "trace_viewer/core/trace_model/event.html",
-  "trace_viewer/core/trace_model/event_container.html",
-  "trace_viewer/core/trace_model/event_info.html",
-  "trace_viewer/core/trace_model/flow_event.html",
-  "trace_viewer/core/trace_model/frame.html",
-  "trace_viewer/core/trace_model/global_memory_dump.html",
-  "trace_viewer/core/trace_model/instant_event.html",
-  "trace_viewer/core/trace_model/interaction_record.html",
-  "trace_viewer/core/trace_model/kernel.html",
-  "trace_viewer/core/trace_model/memory_allocator_dump.html",
-  "trace_viewer/core/trace_model/object_collection.html",
-  "trace_viewer/core/trace_model/object_instance.html",
-  "trace_viewer/core/trace_model/object_snapshot.html",
-  "trace_viewer/core/trace_model/process.html",
-  "trace_viewer/core/trace_model/process_base.html",
-  "trace_viewer/core/trace_model/process_memory_dump.html",
-  "trace_viewer/core/trace_model/proxy_selectable_item.html",
-  "trace_viewer/core/trace_model/rect_annotation.html",
-  "trace_viewer/core/trace_model/sample.html",
-  "trace_viewer/core/trace_model/selectable_item.html",
-  "trace_viewer/core/trace_model/selection_state.html",
-  "trace_viewer/core/trace_model/slice.html",
-  "trace_viewer/core/trace_model/slice_group.html",
-  "trace_viewer/core/trace_model/stack_frame.html",
-  "trace_viewer/core/trace_model/thread.html",
-  "trace_viewer/core/trace_model/thread_slice.html",
-  "trace_viewer/core/trace_model/thread_time_slice.html",
-  "trace_viewer/core/trace_model/time_to_object_instance_map.html",
-  "trace_viewer/core/trace_model/timed_event.html",
-  "trace_viewer/core/trace_model/trace_model.html",
-  "trace_viewer/core/trace_model/trace_model_settings.html",
-  "trace_viewer/core/trace_model/x_marker_annotation.html",
-  "trace_viewer/core/tracks/alert_track.html",
-  "trace_viewer/core/tracks/annotation_view.html",
-  "trace_viewer/core/tracks/async_slice_group_track.html",
-  "trace_viewer/core/tracks/chart_axis.html",
-  "trace_viewer/core/tracks/chart_point.html",
-  "trace_viewer/core/tracks/chart_series.html",
-  "trace_viewer/core/tracks/chart_track.html",
-  "trace_viewer/core/tracks/chart_transform.html",
-  "trace_viewer/core/tracks/comment_box_annotation_view.html",
-  "trace_viewer/core/tracks/container_track.html",
-  "trace_viewer/core/tracks/counter_track.html",
-  "trace_viewer/core/tracks/cpu_track.html",
-  "trace_viewer/core/tracks/drawing_container.html",
-  "trace_viewer/core/tracks/frame_track.html",
-  "trace_viewer/core/tracks/global_memory_dump_track.html",
-  "trace_viewer/core/tracks/heading_track.html",
-  "trace_viewer/core/tracks/highlighter.html",
-  "trace_viewer/core/tracks/kernel_track.html",
-  "trace_viewer/core/tracks/letter_dot_track.html",
-  "trace_viewer/core/tracks/memory_dump_track_util.html",
-  "trace_viewer/core/tracks/multi_row_track.html",
-  "trace_viewer/core/tracks/object_instance_group_track.html",
-  "trace_viewer/core/tracks/object_instance_track.html",
-  "trace_viewer/core/tracks/process_memory_dump_track.html",
-  "trace_viewer/core/tracks/process_summary_track.html",
-  "trace_viewer/core/tracks/process_track.html",
-  "trace_viewer/core/tracks/process_track_base.html",
-  "trace_viewer/core/tracks/rect_annotation_view.html",
-  "trace_viewer/core/tracks/rect_track.html",
-  "trace_viewer/core/tracks/ruler_track.html",
-  "trace_viewer/core/tracks/sample_track.html",
-  "trace_viewer/core/tracks/slice_group_track.html",
-  "trace_viewer/core/tracks/slice_track.html",
-  "trace_viewer/core/tracks/spacing_track.html",
-  "trace_viewer/core/tracks/stacked_bars_track.html",
-  "trace_viewer/core/tracks/thread_track.html",
-  "trace_viewer/core/tracks/trace_model_track.html",
-  "trace_viewer/core/tracks/track.html",
-  "trace_viewer/core/tracks/x_marker_annotation_view.html",
-  "trace_viewer/core/ui_state.html",
-  "trace_viewer/extras/about_tracing/about_tracing.html",
-  "trace_viewer/extras/about_tracing/inspector_connection.html",
-  "trace_viewer/extras/about_tracing/inspector_tracing_controller_client.html",
-  "trace_viewer/extras/about_tracing/profiling_view.html",
-  "trace_viewer/extras/about_tracing/record_and_capture_controller.html",
-  "trace_viewer/extras/about_tracing/record_selection_dialog.html",
-  "trace_viewer/extras/about_tracing/tracing_controller_client.html",
-  "trace_viewer/extras/about_tracing/xhr_based_tracing_controller_client.html",
-  "trace_viewer/extras/analysis/sampling_summary.html",
-  "trace_viewer/extras/audits/android_app.html",
-  "trace_viewer/extras/audits/android_auditor.html",
-  "trace_viewer/extras/audits/android_model_helper.html",
-  "trace_viewer/extras/audits/android_surface_flinger.html",
-  "trace_viewer/extras/audits/utils.html",
-  "trace_viewer/extras/chrome/cc/cc.html",
-  "trace_viewer/extras/chrome/cc/constants.html",
-  "trace_viewer/extras/chrome/cc/debug_colors.html",
-  "trace_viewer/extras/chrome/cc/display_item_debugger.html",
-  "trace_viewer/extras/chrome/cc/display_item_list.html",
-  "trace_viewer/extras/chrome/cc/display_item_view.html",
-  "trace_viewer/extras/chrome/cc/input_latency_async_slice.html",
-  "trace_viewer/extras/chrome/cc/layer_impl.html",
-  "trace_viewer/extras/chrome/cc/layer_picker.html",
-  "trace_viewer/extras/chrome/cc/layer_tree_host_impl.html",
-  "trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.html",
-  "trace_viewer/extras/chrome/cc/layer_tree_impl.html",
-  "trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view.html",
-  "trace_viewer/extras/chrome/cc/layer_view.html",
-  "trace_viewer/extras/chrome/cc/picture.html",
-  "trace_viewer/extras/chrome/cc/picture_as_image_data.html",
-  "trace_viewer/extras/chrome/cc/picture_debugger.html",
-  "trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.html",
-  "trace_viewer/extras/chrome/cc/picture_ops_chart_view.html",
-  "trace_viewer/extras/chrome/cc/picture_ops_list_view.html",
-  "trace_viewer/extras/chrome/cc/picture_view.html",
-  "trace_viewer/extras/chrome/cc/raster_task.html",
-  "trace_viewer/extras/chrome/cc/raster_task_selection.html",
-  "trace_viewer/extras/chrome/cc/raster_task_view.html",
-  "trace_viewer/extras/chrome/cc/region.html",
-  "trace_viewer/extras/chrome/cc/render_pass.html",
-  "trace_viewer/extras/chrome/cc/selection.html",
-  "trace_viewer/extras/chrome/cc/tile.html",
-  "trace_viewer/extras/chrome/cc/tile_coverage_rect.html",
-  "trace_viewer/extras/chrome/cc/tile_view.html",
-  "trace_viewer/extras/chrome/cc/util.html",
-  "trace_viewer/extras/chrome/chrome_auditor.html",
-  "trace_viewer/extras/chrome/chrome_browser_helper.html",
-  "trace_viewer/extras/chrome/chrome_model_helper.html",
-  "trace_viewer/extras/chrome/chrome_process_helper.html",
-  "trace_viewer/extras/chrome/chrome_renderer_helper.html",
-  "trace_viewer/extras/chrome/gpu/gpu.html",
-  "trace_viewer/extras/chrome/gpu/gpu_async_slice.html",
-  "trace_viewer/extras/chrome/gpu/state.html",
-  "trace_viewer/extras/chrome/gpu/state_view.html",
-  "trace_viewer/extras/chrome_config.html",
-  "trace_viewer/extras/full_config.html",
-  "trace_viewer/extras/highlighter/vsync_highlighter.html",
-  "trace_viewer/extras/importer/battor_importer.html",
-  "trace_viewer/extras/importer/ddms_importer.html",
-  "trace_viewer/extras/importer/etw/etw_importer.html",
-  "trace_viewer/extras/importer/etw/eventtrace_parser.html",
-  "trace_viewer/extras/importer/etw/parser.html",
-  "trace_viewer/extras/importer/etw/process_parser.html",
-  "trace_viewer/extras/importer/etw/thread_parser.html",
-  "trace_viewer/extras/importer/gzip_importer.html",
-  "trace_viewer/extras/importer/jszip.html",
-  "trace_viewer/extras/importer/linux_perf/android_parser.html",
-  "trace_viewer/extras/importer/linux_perf/bus_parser.html",
-  "trace_viewer/extras/importer/linux_perf/clock_parser.html",
-  "trace_viewer/extras/importer/linux_perf/cpufreq_parser.html",
-  "trace_viewer/extras/importer/linux_perf/disk_parser.html",
-  "trace_viewer/extras/importer/linux_perf/drm_parser.html",
-  "trace_viewer/extras/importer/linux_perf/exynos_parser.html",
-  "trace_viewer/extras/importer/linux_perf/ftrace_importer.html",
-  "trace_viewer/extras/importer/linux_perf/gesture_parser.html",
-  "trace_viewer/extras/importer/linux_perf/i915_parser.html",
-  "trace_viewer/extras/importer/linux_perf/irq_parser.html",
-  "trace_viewer/extras/importer/linux_perf/kfunc_parser.html",
-  "trace_viewer/extras/importer/linux_perf/mali_parser.html",
-  "trace_viewer/extras/importer/linux_perf/memreclaim_parser.html",
-  "trace_viewer/extras/importer/linux_perf/parser.html",
-  "trace_viewer/extras/importer/linux_perf/power_parser.html",
-  "trace_viewer/extras/importer/linux_perf/regulator_parser.html",
-  "trace_viewer/extras/importer/linux_perf/sched_parser.html",
-  "trace_viewer/extras/importer/linux_perf/sync_parser.html",
-  "trace_viewer/extras/importer/linux_perf/workqueue_parser.html",
-  "trace_viewer/extras/importer/trace2html_importer.html",
-  "trace_viewer/extras/importer/trace_event_importer.html",
-  "trace_viewer/extras/importer/v8/codemap.html",
-  "trace_viewer/extras/importer/v8/log_reader.html",
-  "trace_viewer/extras/importer/v8/splaytree.html",
-  "trace_viewer/extras/importer/v8/v8_log_importer.html",
-  "trace_viewer/extras/importer/zip_importer.html",
-  "trace_viewer/extras/lean_config.html",
-  "trace_viewer/extras/net/net.html",
-  "trace_viewer/extras/net/net_async_slice.html",
-  "trace_viewer/extras/rail/rail_interaction_record.html",
-  "trace_viewer/extras/rail/rail_ir_finder.html",
-  "trace_viewer/extras/side_panel/alerts_side_panel.html",
-  "trace_viewer/extras/side_panel/input_latency.html",
-  "trace_viewer/extras/side_panel/time_summary.html",
-  "trace_viewer/extras/system_stats/system_stats.html",
-  "trace_viewer/extras/system_stats/system_stats_instance_track.html",
-  "trace_viewer/extras/system_stats/system_stats_snapshot.html",
-  "trace_viewer/extras/system_stats/system_stats_snapshot_view.html",
-  "trace_viewer/extras/systrace_config.html",
-  "trace_viewer/extras/tcmalloc/heap.html",
-  "trace_viewer/extras/tcmalloc/heap_instance_track.html",
-  "trace_viewer/extras/tcmalloc/tcmalloc.html",
-  "trace_viewer/extras/tcmalloc/tcmalloc_instance_view.html",
-  "trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.html",
-  "trace_viewer/extras/tquery/context.html",
-  "trace_viewer/extras/tquery/filter.html",
-  "trace_viewer/extras/tquery/filter_all_of.html",
-  "trace_viewer/extras/tquery/filter_any_of.html",
-  "trace_viewer/extras/tquery/filter_has_ancestor.html",
-  "trace_viewer/extras/tquery/filter_has_duration.html",
-  "trace_viewer/extras/tquery/filter_has_title.html",
-  "trace_viewer/extras/tquery/filter_is_top_level.html",
-  "trace_viewer/extras/tquery/tquery.html",
-  "trace_viewer/trace_viewer.html",
-]
-tracing_img_files = [
-  "trace_viewer/base/images/chrome-left.png",
-  "trace_viewer/base/images/chrome-mid.png",
-  "trace_viewer/base/images/chrome-right.png",
-  "trace_viewer/base/images/ui-states.png",
-  "trace_viewer/extras/chrome/cc/images/input-event.png",
-  "trace_viewer/extras/chrome/gpu/images/checkerboard.png",
-  "trace_viewer/extras/tcmalloc/images/collapse.png",
-  "trace_viewer/extras/tcmalloc/images/expand.png",
-]
+gypi_values = exec_script("//build/gypi_to_gn.py",
+                          [ rebase_path("trace_viewer.gypi") ],
+                          "scope",
+                          [ "trace_viewer.gypi" ])
 
 # TODO: ideally this would go into the target_gen_dir, but this requires some
 # changes to the scripts that process them.
@@ -401,8 +14,8 @@
 action("generate_about_tracing") {
   script = "trace_viewer/build/generate_about_tracing_contents"
 
-  inputs = tracing_css_files + tracing_js_html_files +
-    tracing_img_files
+  inputs = gypi_values.tracing_css_files + gypi_values.tracing_js_html_files +
+      gypi_values.tracing_img_files
   outputs = [
     "$output_resource_dir/about_tracing.js",
     "$output_resource_dir/about_tracing.html",
diff --git a/trace-viewer/README.md b/trace-viewer/README.md
index 351c1cf..78417b0 100644
--- a/trace-viewer/README.md
+++ b/trace-viewer/README.md
@@ -11,7 +11,7 @@
 
 It provides rich analysis and visualization capabilities for many types of trace
 files. Its particularly good at viewing linux kernel traces (aka [ftrace](https://www.kernel.org/doc/Documentation/trace/ftrace.txt)) and Chrome's
-[trace_event format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit). Trace viewer can be [embedded](https://github.com/google/trace-viewer/wiki/Embedding) as a component in your own code, or used from a plain checkout to turn trace files into standalone, emailable HTML files from the commandline:
+[trace_event format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview). Trace viewer can be [embedded](https://github.com/google/trace-viewer/wiki/Embedding) as a component in your own code, or used from a plain checkout to turn trace files into standalone, emailable HTML files from the commandline:
 
     trace2html my_trace.json --output=my_trace.html && open my_trace.html
 
diff --git a/trace-viewer/bin/index.html b/trace-viewer/bin/index.html
index ce28005..56b2b6a 100644
--- a/trace-viewer/bin/index.html
+++ b/trace-viewer/bin/index.html
@@ -8,7 +8,8 @@
 <script>
 function onTraceViewerImportFail() {
   document.addEventListener('DOMContentLoaded', function() {
-    document.body.textContent = 'bin/trace_viewer_full.html is missing. Run vulcanize_trace_viewer from $TRACE_VIEWER and reload.';
+    document.body.textContent = 'bin/trace_viewer_full.html is missing. ' +
+        'Run vulcanize_trace_viewer from $TRACE_VIEWER and reload.';
   });
 }
 </script>
@@ -30,7 +31,7 @@
 </style>
 <script>
 document.addEventListener('DOMContentLoaded', function() {
-  var viewer = new tv.TraceViewer('../test_data/big_trace.json');
+  var viewer = new tr.TraceViewer('../test_data/big_trace.json');
   viewer.id = 'trace-viewer';
   viewer.tabIndex = 1;
   document.body.appendChild(viewer);
@@ -39,4 +40,4 @@
 </head>
 <body>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/trace-viewer/examples/chrome_inspect_test_shell.html b/trace-viewer/examples/chrome_inspect_test_shell.html
index dac950b..56790b8 100644
--- a/trace-viewer/examples/chrome_inspect_test_shell.html
+++ b/trace-viewer/examples/chrome_inspect_test_shell.html
@@ -44,7 +44,7 @@
 
   function onLoad() {
     if (window.DevToolsHost === undefined) {
-      tv.showPanic(
+      tr.showPanic(
           'This page only works when launched from chrome://inspect',
           'Try going to ' +
           'chrome://inspect/?browser-inspector=' +
@@ -55,8 +55,8 @@
       return;
     }
 
-    var tracingControllerClient = new tv.e.about_tracing.InspectorTracingControllerClient();
-    profilingViewEl = new tv.e.about_tracing.ProfilingView(tracingControllerClient);
+    var tracingControllerClient = new tr.e.about_tracing.InspectorTracingControllerClient(); // @suppress longLineCheck
+    profilingViewEl = new tr.e.about_tracing.ProfilingView(tracingControllerClient); // @suppress longLineCheck
     document.body.appendChild(profilingViewEl);
   }
   window.addEventListener('load', onLoad);
diff --git a/trace-viewer/examples/deep_reports.html b/trace-viewer/examples/deep_reports.html
index 5781f57..24def60 100644
--- a/trace-viewer/examples/deep_reports.html
+++ b/trace-viewer/examples/deep_reports.html
@@ -26,12 +26,12 @@
 </head>
 <body>
   <select id="trace-dir"></select>
-  <tv-e-dr-html-results id="results"></tv-e-dr-html-results>
+  <tr-e-dr-html-results id="results"></tr-e-dr-html-results>
   <script>
   'use strict';
 
   function onLoad() {
-    tv.b.getAsync('/json/examples').then(function(data) {
+    tr.b.getAsync('/json/examples').then(function(data) {
       var select = document.querySelector('#trace-file');
       var all_files = JSON.parse(data);
       var files = all_files.filter(function(file) {
@@ -76,7 +76,7 @@
     var selectEl = document.body.querySelector('#trace-dir');
     selectEl.filesByDirName = filesByDirName;
 
-    tv.b.iterItems(filesByDirName, function(dirName, filesInDir) {
+    tr.b.iterItems(filesByDirName, function(dirName, filesInDir) {
       var runEl = document.createElement('option');
       runEl.textContent = dirName + ': ' + filesInDir.length + ' traces';
       runEl.value = dirName;
@@ -119,11 +119,11 @@
     var filesInDir = selectEl.filesByDirName[dirName];
     var results = document.querySelector('#results');
     results.clear();
-    tv.e.deep_reports.main(results, filesInDir).then(
+    tr.e.deep_reports.main(results, filesInDir).then(
       function success() {
       },
       function error(err) {
-        tv.showPanic('Error', err);
+        tr.showPanic('Error', err);
       });
   }
   </script>
diff --git a/trace-viewer/examples/skia_debugger.html b/trace-viewer/examples/skia_debugger.html
index fabcebb..3f9971a 100644
--- a/trace-viewer/examples/skia_debugger.html
+++ b/trace-viewer/examples/skia_debugger.html
@@ -35,10 +35,10 @@
   var debuggerEl;
 
   function getPicture(skp64) {
-    if (!tv.e.cc.PictureSnapshot.CanGetInfo()) {
-      console.error(tv.e.cc.PictureSnapshot.HowToEnablePictureDebugging());
+    if (!tr.e.cc.PictureSnapshot.CanGetInfo()) {
+      console.error(tr.e.cc.PictureSnapshot.HowToEnablePictureDebugging());
 
-      var infoBar = document.createElement('tv-b-ui-info-bar');
+      var infoBar = document.createElement('tr-b-ui-info-bar');
       var view = document.querySelector('.view');
 
       view.removeChild(debuggerEl);
@@ -46,7 +46,7 @@
 
       view.appendChild(infoBar);
 
-      infoBar.message = tv.e.cc.PictureSnapshot.HowToEnablePictureDebugging();
+      infoBar.message = tr.e.cc.PictureSnapshot.HowToEnablePictureDebugging();
       infoBar.visible = true;
       return undefined;
     }
@@ -55,9 +55,9 @@
     if (size === undefined)
       throw new Error('Unable to get picture information');
 
-    return new tv.e.cc.Picture(skp64,
-        tv.Rect.fromXYWH(0, 0, size.width, size.height),
-        tv.Rect.fromXYWH(0, 0, size.width, size.height));
+    return new tr.e.cc.Picture(skp64,
+        tr.Rect.fromXYWH(0, 0, size.width, size.height),
+        tr.Rect.fromXYWH(0, 0, size.width, size.height));
   }
 
   function utf8_to_b64(str) {
@@ -143,7 +143,7 @@
   }
 
   function onLoad() {
-    debuggerEl = new tv.e.cc.PictureDebugger();
+    debuggerEl = new tr.e.cc.PictureDebugger();
     document.querySelector('.view').appendChild(debuggerEl);
 
     getAsync('/json/examples/skp', function(data) {
diff --git a/trace-viewer/examples/trace_viewer.html b/trace-viewer/examples/trace_viewer.html
index b3df625..4d2caa1 100644
--- a/trace-viewer/examples/trace_viewer.html
+++ b/trace-viewer/examples/trace_viewer.html
@@ -62,11 +62,11 @@
 
 
   function getAsync(url, cb) {
-    tv.b.getAsync(url).then(cb);
+    tr.b.getAsync(url).then(cb);
   }
 
   function createViewFromTraces(filenames, traces) {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var p = m.importTracesWithProgressDialog(traces, true);
     p.then(
       function() {
@@ -78,8 +78,8 @@
         timelineViewEl.viewTitle = '';
       },
       function(err) {
-        var overlay = new tv.b.ui.Overlay();
-        overlay.textContent = tv.b.normalizeException(err).message;
+        var overlay = new tr.b.ui.Overlay();
+        overlay.textContent = tr.b.normalizeException(err).message;
         overlay.title = 'Import error';
         overlay.visible = true;
       });
@@ -105,7 +105,7 @@
   }
 
   function cleanFilename(file) {
-    var m = /..\/test_data\/(.+)/.exec(file);
+    var m = /\/test_data\/(.+)/.exec(file);
     var rest = m[1];
 
     function upcase(letter) {
@@ -128,7 +128,7 @@
 
   function onLoad() {
     timelineViewEl = document.querySelector('x-timeline-view');
-    tv.b.ui.decorate(timelineViewEl, tv.TraceViewer);
+    tr.b.ui.decorate(timelineViewEl, tr.TraceViewer);
 
     var selectEl = document.createElement('select');
     selectEl.id = 'trace-file';
@@ -138,7 +138,7 @@
       var select = document.querySelector('#trace-file');
       var files = JSON.parse(data);
       files = files.map(function(rest) {
-        return '../test_data/' + rest;
+        return '/test_data/' + rest;
       });
 
       for (var i = 0; i < files.length; ++i) {
diff --git a/trace-viewer/hooks/checklicenses.py b/trace-viewer/hooks/checklicenses.py
new file mode 100755
index 0000000..d9f1ef0
--- /dev/null
+++ b/trace-viewer/hooks/checklicenses.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 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.
+
+'''Makes sure that all files contain proper licensing information.'''
+
+
+import json
+import optparse
+import os.path
+import subprocess
+import sys
+
+import logging
+
+def PrintUsage():
+  print '''Usage: python checklicenses.py [--root <root>] [tocheck]
+  --root   Specifies the repository root. This defaults to '../..' relative
+           to the script file. This will be correct given the normal location
+           of the script in '<root>/tools/checklicenses'.
+
+  tocheck  Specifies the directory, relative to root, to check. This defaults
+           to '.' so it checks everything.
+
+Examples:
+  python checklicenses.py
+  python checklicenses.py --root ~/chromium/src third_party'''
+
+
+WHITELISTED_LICENSES = [
+    'Apache (v2.0)',
+    'BSD (3 clause)',
+    'BSD-like',
+    'MIT/X11 (BSD like)',
+    'zlib/libpng',
+]
+
+
+PATH_SPECIFIC_WHITELISTED_LICENSES = {
+    'third_party/devscripts': [
+        'GPL (v2 or later)',
+    ],
+}
+
+
+def check_licenses(base_directory, target_directory=None):
+  # Figure out which directory we have to check.
+  if not target_directory:
+    # No directory to check specified, use the repository root.
+    start_dir = base_directory
+  else:
+    # Directory specified. Start here. It's supposed to be relative to the
+    # base directory.
+    start_dir = os.path.abspath(os.path.join(base_directory, target_directory))
+
+  logging.info('Using base directory: %s' % base_directory)
+  logging.info('Checking: %s' % start_dir)
+  logging.info('')
+
+  licensecheck_path = os.path.abspath(os.path.join(base_directory,
+                                                   'third_party',
+                                                   'devscripts',
+                                                   'licensecheck.pl'))
+
+  licensecheck = subprocess.Popen([licensecheck_path,
+                                   '-l', '100',
+                                   '-r', start_dir],
+                                  stdout=subprocess.PIPE,
+                                  stderr=subprocess.PIPE)
+  stdout, stderr = licensecheck.communicate()
+  logging.info('----------- licensecheck stdout -----------')
+  logging.info(stdout)
+  logging.info('--------- end licensecheck stdout ---------')
+  if licensecheck.returncode != 0 or stderr:
+    print '----------- licensecheck stderr -----------'
+    print stderr
+    print '--------- end licensecheck stderr ---------'
+    return 1
+
+  used_suppressions = set()
+  errors = []
+
+  for line in stdout.splitlines():
+    filename, license = line.split(':', 1)
+    filename = os.path.relpath(filename.strip(), base_directory)
+
+    # All files in the build output directory are generated one way or another.
+    # There's no need to check them.
+    if filename.startswith('out/'):
+      continue
+
+    # For now we're just interested in the license.
+    license = license.replace('*No copyright*', '').strip()
+
+    # Skip generated files.
+    if 'GENERATED FILE' in license:
+      continue
+
+    if license in WHITELISTED_LICENSES:
+      continue
+
+    matched_prefixes = [
+        prefix for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES
+        if filename.startswith(prefix) and
+        license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]]
+    if matched_prefixes:
+      used_suppressions.update(set(matched_prefixes))
+      continue
+
+    errors.append({'filename': filename, 'license': license})
+
+  if errors:
+    for error in errors:
+      print "'%s' has non-whitelisted license '%s'" % (
+          error['filename'], error['license'])
+    print '\nFAILED\n'
+    print 'Please read',
+    print 'http://www.chromium.org/developers/adding-3rd-party-libraries'
+    print 'for more info how to handle the failure.'
+    print
+    print 'Please respect OWNERS of checklicenses.py. Changes violating'
+    print 'this requirement may be reverted.'
+
+    # Do not print unused suppressions so that above message is clearly
+    # visible and gets proper attention. Too much unrelated output
+    # would be distracting and make the important points easier to miss.
+
+    return 1
+
+
+  return 0
+
+
+def main():
+  default_root = os.path.abspath(
+      os.path.join(os.path.dirname(__file__), '..'))
+  option_parser = optparse.OptionParser()
+  option_parser.add_option('--root', default=default_root,
+                           dest='base_directory',
+                           help='Specifies the repository root. This defaults '
+                           "to '..' relative to the script file, which "
+                           'will normally be the repository root.')
+  options, args = option_parser.parse_args()
+
+  target_directory = None
+  if len(args) == 1:
+    target_directory = args[0]
+  elif len(args) > 1:
+    PrintUsage()
+    return 1
+  results = check_licenses(options.base_directory, target_directory)
+  if not results:
+    print 'SUCCESS'
+  return results
+
+
+if '__main__' == __name__:
+  sys.exit(main())
diff --git a/trace-viewer/hooks/install.py b/trace-viewer/hooks/install.py
index f08de57..aa41f3d 100644
--- a/trace-viewer/hooks/install.py
+++ b/trace-viewer/hooks/install.py
@@ -53,6 +53,13 @@
   if sys.platform == 'win32':
     return
 
+  # Remove old pre-commit, see https://github.com/google/trace-viewer/issues/932
+  old_precommit = os.path.join(_TOP_PATH, '.git', 'hooks', 'pre-commit')
+  old_precommit_target = os.path.join(_TOP_PATH, 'hooks', 'pre_commit')
+  if (os.path.islink(old_precommit) and
+      os.path.abspath(os.readlink(old_precommit)) == old_precommit_target):
+    os.remove(old_precommit)
+
   links = []
   links.append(Link(os.path.join('.git', 'hooks', 'pre-push'),
                     os.path.join('hooks/pre_push')))
diff --git a/trace-viewer/hooks/pre_commit.py b/trace-viewer/hooks/pre_commit.py
index 73db275..8ed2fec 100644
--- a/trace-viewer/hooks/pre_commit.py
+++ b/trace-viewer/hooks/pre_commit.py
@@ -78,6 +78,14 @@
     if affected_file.filename.endswith('.svg'):
       return True
 
+    if (affected_file.filename.endswith('.gypi') or
+        affected_file.filename.endswith('.gyp') or
+        affected_file.filename.endswith('.gn')):
+      return True
+
+    if self.IsThirdParty(affected_file):
+      return True
+
     # Is test data?
     test_data_path = trace_viewer_project.TraceViewerProject.test_data_path
     if affected_file.absolute_path.startswith(test_data_path):
@@ -85,6 +93,9 @@
 
     return False
 
+  def IsThirdParty(self, affected_file):
+    return affected_file.filename.startswith('third_party')
+
 
 def RunChecks(depot_tools_input_api, depot_tools_output_api):
   input_api = _InputAPI(depot_tools_input_api)
@@ -93,13 +104,8 @@
   from hooks import pre_commit_checks
   results += pre_commit_checks.RunChecks(input_api)
 
-  from trace_viewer.build import check_gyp
-  err = check_gyp.GypCheck()
-  if err:
-    results += [err]
-
-  from trace_viewer.build import check_gn
-  err = check_gn.GnCheck()
+  from trace_viewer.build import check_gypi
+  err = check_gypi.GypiCheck()
   if err:
     results += [err]
 
diff --git a/trace-viewer/hooks/pre_commit_checks.py b/trace-viewer/hooks/pre_commit_checks.py
index c1c1745..b37c986 100644
--- a/trace-viewer/hooks/pre_commit_checks.py
+++ b/trace-viewer/hooks/pre_commit_checks.py
@@ -6,6 +6,8 @@
 import sys
 import time
 
+import checklicenses
+
 def _FormatError(msg, files):
   return ('%s in these files:\n' % msg +
       '\n'.join(['  ' + x for x in files])
@@ -50,6 +52,28 @@
   return errors
 
 def CheckCopyright(input_api):
+  results = []
+  results += _CheckCopyrightThirdParty(input_api)
+  results += _CheckCopyrightNonThirdParty(input_api)
+  return results
+
+def _CheckCopyrightThirdParty(input_api):
+  results = []
+  has_third_party_change = any(
+      input_api.IsThirdParty(f)
+      for f in input_api.AffectedFiles(include_deletes=False))
+  if has_third_party_change:
+    trace_viewer_root = os.path.abspath(
+        os.path.join(os.path.dirname(__file__), '..'))
+    trace_viewer_third_party = os.path.join(trace_viewer_root, 'third_party')
+    has_invalid_license = checklicenses.check_licenses(
+        trace_viewer_root, trace_viewer_third_party)
+    if has_invalid_license:
+      results.append(
+          'License check encountered invalid licenses in third_party/.')
+  return results
+
+def _CheckCopyrightNonThirdParty(input_api):
   project_name = 'Chromium'
 
   current_year = int(time.strftime('%Y'))
@@ -85,7 +109,8 @@
   }
   html_license_re = re.compile(html_license_header, re.MULTILINE)
 
-  sources = list(input_api.AffectedFiles(include_deletes=False))
+  sources = list(s for s in input_api.AffectedFiles(include_deletes=False)
+                 if not input_api.IsThirdParty(s))
 
   html_sources = [f for f in sources
                   if os.path.splitext(f.filename)[1] == '.html']
diff --git a/trace-viewer/third_party/components/polymer/layout.html b/trace-viewer/third_party/components/polymer/layout.html
index 55d4d2f..b22cadd 100644
--- a/trace-viewer/third_party/components/polymer/layout.html
+++ b/trace-viewer/third_party/components/polymer/layout.html
@@ -283,4 +283,4 @@
   border-radius: 5px 5px 5px 5px;

 }

 

-</style>
\ No newline at end of file
+</style>
diff --git a/trace-viewer/third_party/css-element-queries/Gruntfile.js b/trace-viewer/third_party/css-element-queries/Gruntfile.js
new file mode 100644
index 0000000..265a0de
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/Gruntfile.js
@@ -0,0 +1,16 @@
+/* jshint node: true */
+module.exports = function(grunt) {
+  'use strict';
+
+  grunt.loadNpmTasks('grunt-bump');
+
+  grunt.initConfig({
+    bump: {
+      options: {
+        files: ['package.json', 'bower.json'],
+        commitFiles: ['package.json', 'bower.json'],
+        pushTo: 'origin'
+      }
+    }
+  });
+};
diff --git a/trace-viewer/third_party/css-element-queries/LICENSE b/trace-viewer/third_party/css-element-queries/LICENSE
new file mode 100644
index 0000000..4de61dc
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2013 Marc J. Schmidt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/trace-viewer/third_party/css-element-queries/README.chromium b/trace-viewer/third_party/css-element-queries/README.chromium
new file mode 100644
index 0000000..0bde0ab
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/README.chromium
@@ -0,0 +1,15 @@
+Name: css-element-queries
+Short Name: css-element-queries
+URL: https://github.com/marcj/css-element-queries
+Version: 0.2.1
+Revision: 996d9035b1a13bb6883c181aad742ae45bd74026
+Date: Thu May 28 13:57:31 2015 +0000
+License File: LICENSE
+Security Critical: no
+
+Description:
+ResizeSensor.js calls a callback when an element is resized for any reason.
+
+Local Modifications:
+Made test/index.html conform to tvcm's expectations: up-cased doctype, added
+'use strict', downloaded mootools from cloudflare and added them to test/.
diff --git a/trace-viewer/third_party/css-element-queries/README.md b/trace-viewer/third_party/css-element-queries/README.md
new file mode 100644
index 0000000..389225e
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/README.md
@@ -0,0 +1,74 @@
+CSS Element Queries
+===================
+
+Element Queries is a polyfill adding support for element based media-queries to all new browsers (incl. IE7+).
+It allows not only to define media-queries based on window-size but also adds 'media-queries' functionality depending on element (any selector supported)
+size while not causing performance lags due to event based implementation.
+
+It's a proof-of-concept event-based CSS element dimension query with valid CSS selector syntax.
+
+Features:
+
+ - no performance issues since it listens only on size changes of elements that have element query rules defined through css. Other element query polifills only listen on `window.onresize` which causes performance issues and allows only to detect changes via window.resize event and not inside layout changes like css3 animation, :hover, DOM changes etc.
+ - no interval/timeout detection. Truly event-based through integrated ResizeSensor class.
+ - no CSS modifications. Valid CSS Syntax
+ - all CSS selectors available. Uses regular attribute selector. No need to write rules in HTML.
+ - supports and tested in webkit, gecko and IE(7/8/9/10/11).
+ - `min-width`, `min-height`, `max-width` and `max-height` are supported so far
+ - works with any layout modifications: HTML (innerHTML etc), inline styles, DOM mutation, CSS3 transitions, fluid layout changes (also percent changes), pseudo classes (:hover etc.), window resizes and more
+ - no Javascript-Framework dependency (works with jQuery, Mootools, etc.)
+
+More demos and information: http://marcj.github.io/css-element-queries/
+
+Example
+-------
+
+```css
+.widget-name {
+    padding: 25px;
+}
+.widget-name[max-width="200px"] {
+    padding: 0;
+}
+.widget-name[min-width="500px"] {
+    padding: 55px;
+}
+
+/* responsive images */
+.responsive-image img {
+    width: 100%;
+}
+
+.responsive-image[max-width^='400px'] img {
+    content: url(demo/image-400px.jpg);
+}
+
+.responsive-image[max-width^='1000px'] img {
+    content: url(demo/image-1000px.jpg);
+}
+
+.responsive-image[min-width='1000px'] img {
+    content: url(demo/image-full.jpg);
+}
+```
+
+Include the javascript files at the bottom and you're good to go. No custom javascript calls needed.
+
+```html
+<script src="src/ResizeSensor.js"></script>
+<script src="src/ElementQueries.js"></script>
+```
+
+Issues
+------
+
+ - So far does not work on `img` and other elements that can't contain other elements. Wrapping with a `div` works fine though (See demo).
+ - Adds additional hidden elements into selected target element and forces target element to be relative or absolute.
+ 
+
+[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/marcj/css-element-queries/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
+
+
+License
+-------
+MIT license. Copyright [Marc J. Schmidt](http://marcjschmidt.de/).
diff --git a/trace-viewer/third_party/css-element-queries/bower.json b/trace-viewer/third_party/css-element-queries/bower.json
new file mode 100644
index 0000000..0295673
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/bower.json
@@ -0,0 +1,19 @@
+{
+  "name": "css-element-queries",
+  "version": "0.2.1",
+  "main": [
+    "./src/ElementQueries.js",
+    "./src/ResizeSensor.js"
+  ],
+  "ignore": [
+    "**/.*",
+    "_*",
+    "Gruntfile.js",
+    "composer.json",
+    "package.json",
+    "*.html"
+  ],
+  "dependencies": {
+  }
+}
+
diff --git a/trace-viewer/third_party/css-element-queries/package.json b/trace-viewer/third_party/css-element-queries/package.json
new file mode 100644
index 0000000..a68c90e
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/package.json
@@ -0,0 +1,26 @@
+{
+  "name": "css-element-queries",
+  "version": "0.2.1",
+  "description": "CSS-Element-Queries Polyfill. proof-of-concept for high-speed element dimension/media queries in valid css.",
+  "main": "src/ElementQueries.js",
+  "directories": {
+    "test": "test"
+  },
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git@github.com:marcj/css-element-queries.git"
+  },
+  "author": "Marc J. Schmidt",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/marcj/css-element-queries/issues"
+  },
+  "homepage": "https://github.com/marcj/css-element-queries",
+  "devDependencies": {
+    "grunt": "^0.4.5",
+    "grunt-bump": "^0.3.1"
+  }
+}
diff --git a/trace-viewer/third_party/css-element-queries/src/ElementQueries.js b/trace-viewer/third_party/css-element-queries/src/ElementQueries.js
new file mode 100755
index 0000000..3287b8d
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/src/ElementQueries.js
@@ -0,0 +1,340 @@
+/**
+ * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
+ * directory of this distribution and at
+ * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
+ */
+;
+(function() {
+    /**
+     *
+     * @type {Function}
+     * @constructor
+     */
+    var ElementQueries = this.ElementQueries = function() {
+
+        this.withTracking = false;
+        var elements = [];
+
+        /**
+         *
+         * @param element
+         * @returns {Number}
+         */
+        function getEmSize(element) {
+            if (!element) {
+                element = document.documentElement;
+            }
+            var fontSize = getComputedStyle(element, 'fontSize');
+            return parseFloat(fontSize) || 16;
+        }
+
+        /**
+         *
+         * @copyright https://github.com/Mr0grog/element-query/blob/master/LICENSE
+         *
+         * @param {HTMLElement} element
+         * @param {*} value
+         * @returns {*}
+         */
+        function convertToPx(element, value) {
+            var units = value.replace(/[0-9]*/, '');
+            value = parseFloat(value);
+            switch (units) {
+                case "px":
+                    return value;
+                case "em":
+                    return value * getEmSize(element);
+                case "rem":
+                    return value * getEmSize();
+                // Viewport units!
+                // According to http://quirksmode.org/mobile/tableViewport.html
+                // documentElement.clientWidth/Height gets us the most reliable info
+                case "vw":
+                    return value * document.documentElement.clientWidth / 100;
+                case "vh":
+                    return value * document.documentElement.clientHeight / 100;
+                case "vmin":
+                case "vmax":
+                    var vw = document.documentElement.clientWidth / 100;
+                    var vh = document.documentElement.clientHeight / 100;
+                    var chooser = Math[units === "vmin" ? "min" : "max"];
+                    return value * chooser(vw, vh);
+                default:
+                    return value;
+                // for now, not supporting physical units (since they are just a set number of px)
+                // or ex/ch (getting accurate measurements is hard)
+            }
+        }
+
+        /**
+         *
+         * @param {HTMLElement} element
+         * @constructor
+         */
+        function SetupInformation(element) {
+            this.element = element;
+            this.options = {};
+            var key, option, width = 0, height = 0, value, actualValue, attrValues, attrValue, attrName;
+
+            /**
+             * @param {Object} option {mode: 'min|max', property: 'width|height', value: '123px'}
+             */
+            this.addOption = function(option) {
+                var idx = [option.mode, option.property, option.value].join(',');
+                this.options[idx] = option;
+            };
+
+            var attributes = ['min-width', 'min-height', 'max-width', 'max-height'];
+
+            /**
+             * Extracts the computed width/height and sets to min/max- attribute.
+             */
+            this.call = function() {
+                // extract current dimensions
+                width = this.element.offsetWidth;
+                height = this.element.offsetHeight;
+
+                attrValues = {};
+
+                for (key in this.options) {
+                    if (!this.options.hasOwnProperty(key)){
+                        continue;
+                    }
+                    option = this.options[key];
+
+                    value = convertToPx(this.element, option.value);
+
+                    actualValue = option.property == 'width' ? width : height;
+                    attrName = option.mode + '-' + option.property;
+                    attrValue = '';
+
+                    if (option.mode == 'min' && actualValue >= value) {
+                        attrValue += option.value;
+                    }
+
+                    if (option.mode == 'max' && actualValue <= value) {
+                        attrValue += option.value;
+                    }
+
+                    if (!attrValues[attrName]) attrValues[attrName] = '';
+                    if (attrValue && -1 === (' '+attrValues[attrName]+' ').indexOf(' ' + attrValue + ' ')) {
+                        attrValues[attrName] += ' ' + attrValue;
+                    }
+                }
+
+                for (var k in attributes) {
+                    if (attrValues[attributes[k]]) {
+                        this.element.setAttribute(attributes[k], attrValues[attributes[k]].substr(1));
+                    } else {
+                        this.element.removeAttribute(attributes[k]);
+                    }
+                }
+            };
+        }
+
+        /**
+         * @param {HTMLElement} element
+         * @param {Object}      options
+         */
+        function setupElement(element, options) {
+            if (element.elementQueriesSetupInformation) {
+                element.elementQueriesSetupInformation.addOption(options);
+            } else {
+                element.elementQueriesSetupInformation = new SetupInformation(element);
+                element.elementQueriesSetupInformation.addOption(options);
+                element.elementQueriesSensor = new ResizeSensor(element, function() {
+                    element.elementQueriesSetupInformation.call();
+                });
+            }
+            element.elementQueriesSetupInformation.call();
+
+            if (this.withTracking) {
+                elements.push(element);
+            }
+        }
+
+        /**
+         * @param {String} selector
+         * @param {String} mode min|max
+         * @param {String} property width|height
+         * @param {String} value
+         */
+        function queueQuery(selector, mode, property, value) {
+            var query;
+            if (document.querySelectorAll) query = document.querySelectorAll.bind(document);
+            if (!query && 'undefined' !== typeof $$) query = $$;
+            if (!query && 'undefined' !== typeof jQuery) query = jQuery;
+
+            if (!query) {
+                throw 'No document.querySelectorAll, jQuery or Mootools\'s $$ found.';
+            }
+
+            var elements = query(selector);
+            for (var i = 0, j = elements.length; i < j; i++) {
+                setupElement(elements[i], {
+                    mode: mode,
+                    property: property,
+                    value: value
+                });
+            }
+        }
+
+        var regex = /,?([^,\n]*)\[[\s\t]*(min|max)-(width|height)[\s\t]*[~$\^]?=[\s\t]*"([^"]*)"[\s\t]*]([^\n\s\{]*)/mgi;
+
+        /**
+         * @param {String} css
+         */
+        function extractQuery(css) {
+            var match;
+            css = css.replace(/'/g, '"');
+            while (null !== (match = regex.exec(css))) {
+                if (5 < match.length) {
+                    queueQuery(match[1] || match[5], match[2], match[3], match[4]);
+                }
+            }
+        }
+
+        /**
+         * @param {CssRule[]|String} rules
+         */
+        function readRules(rules) {
+            var selector = '';
+            if (!rules) {
+                return;
+            }
+            if ('string' === typeof rules) {
+                rules = rules.toLowerCase();
+                if (-1 !== rules.indexOf('min-width') || -1 !== rules.indexOf('max-width')) {
+                    extractQuery(rules);
+                }
+            } else {
+                for (var i = 0, j = rules.length; i < j; i++) {
+                    if (1 === rules[i].type) {
+                        selector = rules[i].selectorText || rules[i].cssText;
+                        if (-1 !== selector.indexOf('min-height') || -1 !== selector.indexOf('max-height')) {
+                            extractQuery(selector);
+                        }else if(-1 !== selector.indexOf('min-width') || -1 !== selector.indexOf('max-width')) {
+                            extractQuery(selector);
+                        }
+                    } else if (4 === rules[i].type) {
+                        readRules(rules[i].cssRules || rules[i].rules);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Searches all css rules and setups the event listener to all elements with element query rules..
+         *
+         * @param {Boolean} withTracking allows and requires you to use detach, since we store internally all used elements
+         *                               (no garbage collection possible if you don not call .detach() first)
+         */
+        this.init = function(withTracking) {
+            this.withTracking = withTracking;
+            for (var i = 0, j = document.styleSheets.length; i < j; i++) {
+                try {
+                    readRules(document.styleSheets[i].cssText || document.styleSheets[i].cssRules || document.styleSheets[i].rules);
+                } catch(e) {
+                    if (e.name !== 'SecurityError') {
+                        throw e;
+                    }
+                }
+            }
+        };
+
+        /**
+         *
+         * @param {Boolean} withTracking allows and requires you to use detach, since we store internally all used elements
+         *                               (no garbage collection possible if you don not call .detach() first)
+         */
+        this.update = function(withTracking) {
+            this.withTracking = withTracking;
+            this.init();
+        };
+
+        this.detach = function() {
+            if (!this.withTracking) {
+                throw 'withTracking is not enabled. We can not detach elements since we don not store it.' +
+                'Use ElementQueries.withTracking = true; before domready.';
+            }
+
+            var element;
+            while (element = elements.pop()) {
+                ElementQueries.detach(element);
+            }
+
+            elements = [];
+        };
+    };
+
+    /**
+     *
+     * @param {Boolean} withTracking allows and requires you to use detach, since we store internally all used elements
+     *                               (no garbage collection possible if you don not call .detach() first)
+     */
+    ElementQueries.update = function(withTracking) {
+        ElementQueries.instance.update(withTracking);
+    };
+
+    /**
+     * Removes all sensor and elementquery information from the element.
+     *
+     * @param {HTMLElement} element
+     */
+    ElementQueries.detach = function(element) {
+        if (element.elementQueriesSetupInformation) {
+            element.elementQueriesSensor.detach();
+            delete element.elementQueriesSetupInformation;
+            delete element.elementQueriesSensor;
+            console.log('detached');
+        } else {
+            console.log('detached already', element);
+        }
+    };
+
+    ElementQueries.withTracking = false;
+
+    ElementQueries.init = function() {
+        if (!ElementQueries.instance) {
+            ElementQueries.instance = new ElementQueries();
+        }
+
+        ElementQueries.instance.init(ElementQueries.withTracking);
+    };
+
+    var domLoaded = function (callback) {
+        /* Internet Explorer */
+        /*@cc_on
+        @if (@_win32 || @_win64)
+            document.write('<script id="ieScriptLoad" defer src="//:"><\/script>');
+            document.getElementById('ieScriptLoad').onreadystatechange = function() {
+                if (this.readyState == 'complete') {
+                    callback();
+                }
+            };
+        @end @*/
+        /* Mozilla, Chrome, Opera */
+        if (document.addEventListener) {
+            document.addEventListener('DOMContentLoaded', callback, false);
+        }
+        /* Safari, iCab, Konqueror */
+        if (/KHTML|WebKit|iCab/i.test(navigator.userAgent)) {
+            var DOMLoadTimer = setInterval(function () {
+                if (/loaded|complete/i.test(document.readyState)) {
+                    callback();
+                    clearInterval(DOMLoadTimer);
+                }
+            }, 10);
+        }
+        /* Other web browsers */
+        window.onload = callback;
+    };
+
+    if (window.addEventListener) {
+        window.addEventListener('load', ElementQueries.init, false);
+    } else {
+        window.attachEvent('onload', ElementQueries.init);
+    }
+    domLoaded(ElementQueries.init);
+
+})();
diff --git a/trace-viewer/third_party/css-element-queries/src/ResizeSensor.js b/trace-viewer/third_party/css-element-queries/src/ResizeSensor.js
new file mode 100755
index 0000000..687e17d
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/src/ResizeSensor.js
@@ -0,0 +1,158 @@
+/**
+ * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
+ * directory of this distribution and at
+ * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
+ */
+;
+(function() {
+
+    /**
+     * Class for dimension change detection.
+     *
+     * @param {Element|Element[]|Elements|jQuery} element
+     * @param {Function} callback
+     *
+     * @constructor
+     */
+    this.ResizeSensor = function(element, callback) {
+        /**
+         *
+         * @constructor
+         */
+        function EventQueue() {
+            this.q = [];
+            this.add = function(ev) {
+                this.q.push(ev);
+            };
+
+            var i, j;
+            this.call = function() {
+                for (i = 0, j = this.q.length; i < j; i++) {
+                    this.q[i].call();
+                }
+            };
+        }
+
+        /**
+         * @param {HTMLElement} element
+         * @param {String}      prop
+         * @returns {String|Number}
+         */
+        function getComputedStyle(element, prop) {
+            if (element.currentStyle) {
+                return element.currentStyle[prop];
+            } else if (window.getComputedStyle) {
+                return window.getComputedStyle(element, null).getPropertyValue(prop);
+            } else {
+                return element.style[prop];
+            }
+        }
+
+        /**
+         *
+         * @param {HTMLElement} element
+         * @param {Function}    resized
+         */
+        function attachResizeEvent(element, resized) {
+            if (!element.resizedAttached) {
+                element.resizedAttached = new EventQueue();
+                element.resizedAttached.add(resized);
+            } else if (element.resizedAttached) {
+                element.resizedAttached.add(resized);
+                return;
+            }
+
+            element.resizeSensor = document.createElement('div');
+            element.resizeSensor.className = 'resize-sensor';
+            var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;';
+            var styleChild = 'position: absolute; left: 0; top: 0;';
+
+            element.resizeSensor.style.cssText = style;
+            element.resizeSensor.innerHTML =
+                '<div class="resize-sensor-expand" style="' + style + '">' +
+                    '<div style="' + styleChild + '"></div>' +
+                '</div>' +
+                '<div class="resize-sensor-shrink" style="' + style + '">' +
+                    '<div style="' + styleChild + ' width: 200%; height: 200%"></div>' +
+                '</div>';
+            element.appendChild(element.resizeSensor);
+
+            if (!{fixed: 1, absolute: 1}[getComputedStyle(element, 'position')]) {
+                element.style.position = 'relative';
+            }
+
+            var expand = element.resizeSensor.childNodes[0];
+            var expandChild = expand.childNodes[0];
+            var shrink = element.resizeSensor.childNodes[1];
+            var shrinkChild = shrink.childNodes[0];
+
+            var lastWidth, lastHeight;
+
+            var reset = function() {
+                expandChild.style.width = expand.offsetWidth + 10 + 'px';
+                expandChild.style.height = expand.offsetHeight + 10 + 'px';
+                expand.scrollLeft = expand.scrollWidth;
+                expand.scrollTop = expand.scrollHeight;
+                shrink.scrollLeft = shrink.scrollWidth;
+                shrink.scrollTop = shrink.scrollHeight;
+                lastWidth = element.offsetWidth;
+                lastHeight = element.offsetHeight;
+            };
+
+            reset();
+
+            var changed = function() {
+                if (element.resizedAttached) {
+                    element.resizedAttached.call();
+                }
+            };
+
+            var addEvent = function(el, name, cb) {
+                if (el.attachEvent) {
+                    el.attachEvent('on' + name, cb);
+                } else {
+                    el.addEventListener(name, cb);
+                }
+            };
+
+            addEvent(expand, 'scroll', function() {
+                if (element.offsetWidth > lastWidth || element.offsetHeight > lastHeight) {
+                    changed();
+                }
+                reset();
+            });
+
+            addEvent(shrink, 'scroll',function() {
+                if (element.offsetWidth < lastWidth || element.offsetHeight < lastHeight) {
+                    changed();
+                }
+                reset();
+            });
+        }
+
+        if ("[object Array]" === Object.prototype.toString.call(element)
+            || ('undefined' !== typeof jQuery && element instanceof jQuery) //jquery
+            || ('undefined' !== typeof Elements && element instanceof Elements) //mootools
+            ) {
+            var i = 0, j = element.length;
+            for (; i < j; i++) {
+                attachResizeEvent(element[i], callback);
+            }
+        } else {
+            attachResizeEvent(element, callback);
+        }
+
+        this.detach = function() {
+            ResizeSensor.detach(element);
+        };
+    };
+
+    this.ResizeSensor.detach = function(element) {
+        if (element.resizeSensor) {
+            element.removeChild(element.resizeSensor);
+            delete element.resizeSensor;
+            delete element.resizedAttached;
+        }
+    };
+
+})();
\ No newline at end of file
diff --git a/trace-viewer/third_party/css-element-queries/test/index.html b/trace-viewer/third_party/css-element-queries/test/index.html
new file mode 100644
index 0000000..aedda85
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/test/index.html
@@ -0,0 +1,497 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="chrome=1">
+    <title>Css-element-queries test</title>
+    <script src="mootools-core-full-nocompat.js"></script>
+    <script src="mootools-more-yui-compressed.min.js"></script>
+    <script src="../src/ResizeSensor.js"></script>
+    <script src="../src/ElementQueries.js"></script>
+
+    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+    <!--[if lt IE 9]>
+    <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <script>
+        'use strict';
+        var ResizerDemo = new Class({
+            y: null,
+            initialize: function(container) {
+                this.container = container;
+                this.setupLayout();
+            },
+
+            setupLayout: function(){
+                this.handler = new Element('div', {
+                    'class': 'resizerDemo-handler'
+                }).inject(this.container);
+
+                this.container.makeResizable({
+                    snap: 0,
+                    handle: this.handler,
+                    modifiers: {
+                        'x': 'width',
+                        'y': this.y
+                    }
+                });
+            }
+        });
+
+        var ResizeDemoXY = new Class({
+            Extends: ResizerDemo,
+            y: 'height'
+        });
+
+        window.addEvent('domready', function(){
+            $$('.examplesResizerDemos').each(function(resizer){
+                new ResizerDemo(resizer);
+            });
+            $$('.examplesResizerDemosXY').each(function(resizer){
+                new ResizeDemoXY(resizer);
+            });
+        });
+    </script>
+    <style type="text/css">
+        .examplesResizerDemos,
+        .examplesResizerDemosXY {
+            background-color: white;
+            width: 550px;
+            margin: 15px;
+            padding: 15px 0;
+            position: relative;
+            border-left: 1px dashed silver;
+            border-bottom: 1px dashed silver;
+        }
+
+        .examplesResizerDemosXY {
+            height: 150px;
+        }
+
+        .resizerDemo-handler {
+            position: absolute;
+            right: 0;
+            top: 0;
+            bottom: 0;
+            width: 5px;
+            padding: 0 1px;
+            background-color: gray;
+            cursor: ew-resize;
+            line-height: 5px;
+            font-size: 14px;
+        }
+
+        .resizerDemo-handler:before {
+            content: '• • •';
+            color: white;
+            width: 5px;
+            position: absolute;
+            top: 50%;
+            margin-top: -15px;
+        }
+
+        .example-1 {
+            max-width: 400px;
+            border: 1px solid silver;
+            background-color: #eee;
+            margin: auto;
+            padding: 50px;
+            text-align: center;
+            min-width: 120px;
+            transition:all .2s ease;
+        }
+
+        .example-1[max-width~="400px"] {
+            padding: 5px;
+        }
+
+        .example-1[max-width~="200px"] {
+            text-align: left;
+            font-size: 12px;
+        }
+
+        .example-2 {
+            border: 1px solid silver;
+            margin: 25px;
+            background-color: #eee;
+        }
+
+        .example-2-first,
+        .example-2-second {
+            background-color: black;
+            color: white;
+            padding: 2px;
+            width: 45%;
+            margin: 5px;
+            float: left;
+        }
+
+        .example-2-second {
+            float: right;
+        }
+
+        .example-2-box {
+            background-color: gray;
+            color: white;
+            margin: 5px;
+            padding: 2px;
+        }
+
+        .example-2[max-width~="300px"] .example-2-first,
+        .example-2[max-width~="300px"] .example-2-second {
+            float: none;
+            background-color: #4186ff;
+            width: auto;
+        }
+
+        .example-2[max-width~="350px"] .example-2-box {
+            background-color: #ba9196;
+        }
+
+        .example-2[max-width~="300px"] .example-2-box {
+            background-color: #ba6377;
+        }
+
+        .example-2[max-width~="200px"] .example-2-box {
+            background-color: #ba4349;
+        }
+
+        .example-2[max-width~="100px"] .example-2-box {
+            background-color: #ba000d;
+        }
+
+        .example-3,
+        .example-4 {
+            border: 1px solid silver;
+            margin: 25px;
+            background-color: #eee;
+        }
+
+        #example-5 {
+            overflow: visible;
+            position: relative;
+            z-index: 150;
+            text-align: center;
+        }
+
+        #example-3-box,
+        #example-4-box {
+            background-color: gray;
+            color: white;
+            margin: auto;
+            width: 50%;
+            padding: 50px;
+        }
+
+        .example-3-box-start,
+        .example-4-box-start {
+            animation-duration: 3s;
+            -moz-animation-duration: 3s;
+            -webkit-animation-duration: 3s;
+            -moz-animation-name: anim;
+            animation-name: anim;
+            -webkit-animation-name: anim;
+            animation-iteration-count: infinite;
+            -webkit-animation-iteration-count: infinite;
+        }
+
+        .example-4-box-start {
+            -moz-animation-name: animHeight;
+            animation-name: animHeight;
+            -webkit-animation-name: animHeight;
+        }
+
+        #example-3-log,
+        #example-4-log {
+            background-color: white;
+            padding: 2px;
+            margin: 5px;
+        }
+
+        @keyframes anim {
+            0% {
+                padding: 50px;
+                width: 50%;
+                background-color: gray;
+            }
+
+            50% {
+                padding: 10px;
+                width: 40%;
+                background-color: #806522;
+            }
+
+            100% {
+                padding: 50px;
+                width: 50%;
+                background-color: gray;
+            }
+        }
+
+        @-webkit-keyframes anim {
+            0% {
+                padding: 50px;
+                width: 50%;
+                background-color: gray;
+            }
+
+            50% {
+                padding: 10px;
+                width: 40%;
+                background-color: #806522;
+            }
+
+            100% {
+                padding: 50px;
+                width: 50%;
+                background-color: gray;
+            }
+        }
+
+        @-moz-keyframes anim {
+            0% {
+                padding: 50px;
+                width: 50%;
+                background-color: gray;
+            }
+
+            50% {
+                padding: 10px;
+                width: 40%;
+                background-color: #806522;
+            }
+
+            100% {
+                padding: 50px;
+                width: 50%;
+                background-color: gray;
+            }
+        }
+
+        @keyframes animHeight {
+            0% {
+                padding: 50px;
+                height: 50%;
+                background-color: gray;
+            }
+
+            50% {
+                padding: 10px;
+                height: 40%;
+                background-color: #806522;
+            }
+
+            100% {
+                padding: 50px;
+                height: 50%;
+                background-color: gray;
+            }
+        }
+
+        @-webkit-keyframes animHeight {
+            0% {
+                padding: 50px;
+                height: 50%;
+                background-color: gray;
+            }
+
+            50% {
+                padding: 10px;
+                height: 40%;
+                background-color: #806522;
+            }
+
+            100% {
+                padding: 50px;
+                height: 50%;
+                background-color: gray;
+            }
+        }
+
+        @-moz-keyframes animHeight {
+            0% {
+                padding: 50px;
+                height: 50%;
+                background-color: gray;
+            }
+
+            50% {
+                padding: 10px;
+                height: 40%;
+                background-color: #806522;
+            }
+
+            100% {
+                padding: 50px;
+                height: 50%;
+                background-color: gray;
+            }
+        }
+
+        .dynamicElement {
+            margin: 50px;
+            width: 50px;
+
+            -moz-animation-name: animHeight;
+            animation-name: animHeight;
+            -webkit-animation-name: animHeight;
+
+            animation-duration: 3s;
+            -moz-animation-duration: 3s;
+            -webkit-animation-duration: 3s;
+            animation-iteration-count: infinite;
+            -webkit-animation-iteration-count: infinite;
+
+            display: inline-block;
+            border: 1px solid #eee;
+            background-color: #f9f9f9;
+        }
+
+        .dynamic {
+            margin: 15px;
+        }
+
+    </style>
+</head>
+<body>    
+    Drag the gray line at the right to see it in action.
+    <div class="examples">
+        <div class="examplesResizerDemos">
+            <div class="example-1">
+                <h2>Demo 1</h2>
+                This is content from the first responsive demo without media queries. It uses the element queries provided by this library.
+            </div>
+        </div>
+        <div class="examplesResizerDemos">
+            <div class="example-2">
+                <h2>Demo 2</h2>
+                <div class="example-2-box">
+                    Box
+                </div>
+                <div class="example-2-first">
+                    First 1/2 box
+                </div>
+                <div class="example-2-second">
+                    Second 1/2 box
+                </div>
+                <div class="breaker"></div>
+            </div>
+        </div>
+        <div class="examplesResizerDemos">
+            <div class="example-3">
+                <h2>Demo 3 - width<button id="startStop3">Start/Stop</button></h2>
+                <div id="example-3-box">
+                    This box is animated through css transitions.
+                    We attached a resize-listener to this box. See below.
+                </div>
+                <div id="example-3-log">
+                    No changes.
+                </div>
+            </div>
+        </div>
+        <div class="examplesResizerDemos">
+            <div class="example-4">
+                <h2>Demo 4 - height<button id="startStop4">Start/Stop</button></h2>
+                <div id="example-4-box">
+                    This box is animated through css transitions.
+                    We attached a resize-listener to this box. See below.
+                </div>
+                <div id="example-4-log">
+                    No changes.
+                </div>
+            </div>
+        </div>
+
+        <div style="height: 200px">
+            <div class="examplesResizerDemosXY">
+                <div id="example-5">
+                    0 changes
+                </div>
+            </div>
+        </div>
+        <script>
+            'use strict';
+            (function(){
+                var logger = document.id('example-3-log');
+                var box = document.id('example-3-box');
+                document.id('startStop3').addEvent('click', function(){
+                    if (box.hasClass('example-3-box-start')) {
+                        box.removeClass('example-3-box-start');
+                    } else {
+                        box.addClass('example-3-box-start');
+                    }
+                });
+                new ResizeSensor(box, function(el){
+                    logger.set('html', 'Changed to ' + box.getSize().x+'px width.');
+                });
+            })();
+        </script>
+        <script>
+            'use strict';
+            (function(){
+                var logger = document.id('example-4-log');
+                var box = document.id('example-4-box');
+                document.id('startStop4').addEvent('click', function(){
+                    if (box.hasClass('example-4-box-start')) {
+                        box.removeClass('example-4-box-start');
+                    } else {
+                        box.addClass('example-4-box-start');
+                    }
+                });
+                new ResizeSensor(box, function(){
+                    logger.set('html', 'Changed to ' + box.getSize().y+'px height.');
+                });
+            })();
+        </script>
+        <script>
+            'use strict';
+            (function(){
+                var box = document.id('example-5');
+                var changed = 0;
+                new ResizeSensor(box.getParent(), function(){
+                    box.innerHTML = (++changed) + ' changes. ' + box.getParent().getSize().x+'px/'+box.getParent().getSize().y+'px';
+                });
+            })();
+        </script>
+        <div class="dynamic">
+            <input type="text" value="10" id="dynamicCount" />
+            <button onclick="addDynamic()">Add</button>
+            <button onclick="detachDynamic()">Detach</button>
+            <button onclick="removeDynamic()">Remove</button>
+            <div id="dynamicCounter"></div>
+            <div id="dynamicContainer"></div>
+        </div>
+        <script>
+            'use strict';
+            var container = $('dynamicContainer');
+            var dynamicCount = $('dynamicCount');
+            var dynamicCounter = $('dynamicCounter');
+
+            window.detachDynamic = function() {
+                container.getChildren().each(function(element) {
+                    ResizeSensor.detach(element);
+                });
+            };
+
+            window.removeDynamic = function() {
+                container.empty();
+            };
+
+            window.addDynamic = function() {
+                container.empty();
+                var i = 0, to = dynamicCount.value, div, counter = 0;
+                for (; i < to; i++) {
+                    div = new Element('div', {
+                        'class': 'dynamicElement',
+                        text: '#' + i
+                    }).inject(container);
+
+                    new ResizeSensor(div, function(){
+                        counter++;
+                        dynamicCounter.set('text', counter + ' changes.');
+                    });
+                }
+            }
+        </script>
+    </div>
+</body>
diff --git a/trace-viewer/third_party/css-element-queries/test/mootools-core-full-nocompat.js b/trace-viewer/third_party/css-element-queries/test/mootools-core-full-nocompat.js
new file mode 100644
index 0000000..db83850
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/test/mootools-core-full-nocompat.js
@@ -0,0 +1,5977 @@
+/*
+---
+MooTools: the javascript framework
+
+web build:
+ - http://mootools.net/core/8423c12ffd6a6bfcde9ea22554aec795
+
+packager build:
+ - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady
+
+...
+*/
+
+/*
+---
+
+name: Core
+
+description: The heart of MooTools.
+
+license: MIT-style license.
+
+copyright: Copyright (c) 2006-2014 [Valerio Proietti](http://mad4milk.net/).
+
+authors: The MooTools production team (http://mootools.net/developers/)
+
+inspiration:
+  - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
+  - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
+
+provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
+
+...
+*/
+
+(function(){
+
+this.MooTools = {
+	version: '1.5.0',
+	build: '0f7b690afee9349b15909f33016a25d2e4d9f4e3'
+};
+
+// typeOf, instanceOf
+
+var typeOf = this.typeOf = function(item){
+	if (item == null) return 'null';
+	if (item.$family != null) return item.$family();
+
+	if (item.nodeName){
+		if (item.nodeType == 1) return 'element';
+		if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
+	} else if (typeof item.length == 'number'){
+		if ('callee' in item) return 'arguments';
+		if ('item' in item) return 'collection';
+	}
+
+	return typeof item;
+};
+
+var instanceOf = this.instanceOf = function(item, object){
+	if (item == null) return false;
+	var constructor = item.$constructor || item.constructor;
+	while (constructor){
+		if (constructor === object) return true;
+		constructor = constructor.parent;
+	}
+	/*<ltIE8>*/
+	if (!item.hasOwnProperty) return false;
+	/*</ltIE8>*/
+	return item instanceof object;
+};
+
+// Function overloading
+
+var Function = this.Function;
+
+var enumerables = true;
+for (var i in {toString: 1}) enumerables = null;
+if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
+
+Function.prototype.overloadSetter = function(usePlural){
+	var self = this;
+	return function(a, b){
+		if (a == null) return this;
+		if (usePlural || typeof a != 'string'){
+			for (var k in a) self.call(this, k, a[k]);
+			if (enumerables) for (var i = enumerables.length; i--;){
+				k = enumerables[i];
+				if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
+			}
+		} else {
+			self.call(this, a, b);
+		}
+		return this;
+	};
+};
+
+Function.prototype.overloadGetter = function(usePlural){
+	var self = this;
+	return function(a){
+		var args, result;
+		if (typeof a != 'string') args = a;
+		else if (arguments.length > 1) args = arguments;
+		else if (usePlural) args = [a];
+		if (args){
+			result = {};
+			for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
+		} else {
+			result = self.call(this, a);
+		}
+		return result;
+	};
+};
+
+Function.prototype.extend = function(key, value){
+	this[key] = value;
+}.overloadSetter();
+
+Function.prototype.implement = function(key, value){
+	this.prototype[key] = value;
+}.overloadSetter();
+
+// From
+
+var slice = Array.prototype.slice;
+
+Function.from = function(item){
+	return (typeOf(item) == 'function') ? item : function(){
+		return item;
+	};
+};
+
+Array.from = function(item){
+	if (item == null) return [];
+	return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
+};
+
+Number.from = function(item){
+	var number = parseFloat(item);
+	return isFinite(number) ? number : null;
+};
+
+String.from = function(item){
+	return item + '';
+};
+
+// hide, protect
+
+Function.implement({
+
+	hide: function(){
+		this.$hidden = true;
+		return this;
+	},
+
+	protect: function(){
+		this.$protected = true;
+		return this;
+	}
+
+});
+
+// Type
+
+var Type = this.Type = function(name, object){
+	if (name){
+		var lower = name.toLowerCase();
+		var typeCheck = function(item){
+			return (typeOf(item) == lower);
+		};
+
+		Type['is' + name] = typeCheck;
+		if (object != null){
+			object.prototype.$family = (function(){
+				return lower;
+			}).hide();
+			
+		}
+	}
+
+	if (object == null) return null;
+
+	object.extend(this);
+	object.$constructor = Type;
+	object.prototype.$constructor = object;
+
+	return object;
+};
+
+var toString = Object.prototype.toString;
+
+Type.isEnumerable = function(item){
+	return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
+};
+
+var hooks = {};
+
+var hooksOf = function(object){
+	var type = typeOf(object.prototype);
+	return hooks[type] || (hooks[type] = []);
+};
+
+var implement = function(name, method){
+	if (method && method.$hidden) return;
+
+	var hooks = hooksOf(this);
+
+	for (var i = 0; i < hooks.length; i++){
+		var hook = hooks[i];
+		if (typeOf(hook) == 'type') implement.call(hook, name, method);
+		else hook.call(this, name, method);
+	}
+
+	var previous = this.prototype[name];
+	if (previous == null || !previous.$protected) this.prototype[name] = method;
+
+	if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
+		return method.apply(item, slice.call(arguments, 1));
+	});
+};
+
+var extend = function(name, method){
+	if (method && method.$hidden) return;
+	var previous = this[name];
+	if (previous == null || !previous.$protected) this[name] = method;
+};
+
+Type.implement({
+
+	implement: implement.overloadSetter(),
+
+	extend: extend.overloadSetter(),
+
+	alias: function(name, existing){
+		implement.call(this, name, this.prototype[existing]);
+	}.overloadSetter(),
+
+	mirror: function(hook){
+		hooksOf(this).push(hook);
+		return this;
+	}
+
+});
+
+new Type('Type', Type);
+
+// Default Types
+
+var force = function(name, object, methods){
+	var isType = (object != Object),
+		prototype = object.prototype;
+
+	if (isType) object = new Type(name, object);
+
+	for (var i = 0, l = methods.length; i < l; i++){
+		var key = methods[i],
+			generic = object[key],
+			proto = prototype[key];
+
+		if (generic) generic.protect();
+		if (isType && proto) object.implement(key, proto.protect());
+	}
+
+	if (isType){
+		var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]);
+		object.forEachMethod = function(fn){
+			if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){
+				fn.call(prototype, prototype[methods[i]], methods[i]);
+			}
+			for (var key in prototype) fn.call(prototype, prototype[key], key);
+		};
+	}
+
+	return force;
+};
+
+force('String', String, [
+	'charAt', 'charCodeAt', 'concat', 'contains', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
+	'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase'
+])('Array', Array, [
+	'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
+	'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
+])('Number', Number, [
+	'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
+])('Function', Function, [
+	'apply', 'call', 'bind'
+])('RegExp', RegExp, [
+	'exec', 'test'
+])('Object', Object, [
+	'create', 'defineProperty', 'defineProperties', 'keys',
+	'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
+	'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
+])('Date', Date, ['now']);
+
+Object.extend = extend.overloadSetter();
+
+Date.extend('now', function(){
+	return +(new Date);
+});
+
+new Type('Boolean', Boolean);
+
+// fixes NaN returning as Number
+
+Number.prototype.$family = function(){
+	return isFinite(this) ? 'number' : 'null';
+}.hide();
+
+// Number.random
+
+Number.extend('random', function(min, max){
+	return Math.floor(Math.random() * (max - min + 1) + min);
+});
+
+// forEach, each
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+Object.extend('forEach', function(object, fn, bind){
+	for (var key in object){
+		if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);
+	}
+});
+
+Object.each = Object.forEach;
+
+Array.implement({
+
+	/*<!ES5>*/
+	forEach: function(fn, bind){
+		for (var i = 0, l = this.length; i < l; i++){
+			if (i in this) fn.call(bind, this[i], i, this);
+		}
+	},
+	/*</!ES5>*/
+
+	each: function(fn, bind){
+		Array.forEach(this, fn, bind);
+		return this;
+	}
+
+});
+
+// Array & Object cloning, Object merging and appending
+
+var cloneOf = function(item){
+	switch (typeOf(item)){
+		case 'array': return item.clone();
+		case 'object': return Object.clone(item);
+		default: return item;
+	}
+};
+
+Array.implement('clone', function(){
+	var i = this.length, clone = new Array(i);
+	while (i--) clone[i] = cloneOf(this[i]);
+	return clone;
+});
+
+var mergeOne = function(source, key, current){
+	switch (typeOf(current)){
+		case 'object':
+			if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
+			else source[key] = Object.clone(current);
+		break;
+		case 'array': source[key] = current.clone(); break;
+		default: source[key] = current;
+	}
+	return source;
+};
+
+Object.extend({
+
+	merge: function(source, k, v){
+		if (typeOf(k) == 'string') return mergeOne(source, k, v);
+		for (var i = 1, l = arguments.length; i < l; i++){
+			var object = arguments[i];
+			for (var key in object) mergeOne(source, key, object[key]);
+		}
+		return source;
+	},
+
+	clone: function(object){
+		var clone = {};
+		for (var key in object) clone[key] = cloneOf(object[key]);
+		return clone;
+	},
+
+	append: function(original){
+		for (var i = 1, l = arguments.length; i < l; i++){
+			var extended = arguments[i] || {};
+			for (var key in extended) original[key] = extended[key];
+		}
+		return original;
+	}
+
+});
+
+// Object-less types
+
+['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
+	new Type(name);
+});
+
+// Unique ID
+
+var UID = Date.now();
+
+String.extend('uniqueID', function(){
+	return (UID++).toString(36);
+});
+
+
+
+})();
+
+
+/*
+---
+
+name: Array
+
+description: Contains Array Prototypes like each, contains, and erase.
+
+license: MIT-style license.
+
+requires: [Type]
+
+provides: Array
+
+...
+*/
+
+Array.implement({
+
+	/*<!ES5>*/
+	every: function(fn, bind){
+		for (var i = 0, l = this.length >>> 0; i < l; i++){
+			if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
+		}
+		return true;
+	},
+
+	filter: function(fn, bind){
+		var results = [];
+		for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){
+			value = this[i];
+			if (fn.call(bind, value, i, this)) results.push(value);
+		}
+		return results;
+	},
+
+	indexOf: function(item, from){
+		var length = this.length >>> 0;
+		for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){
+			if (this[i] === item) return i;
+		}
+		return -1;
+	},
+
+	map: function(fn, bind){
+		var length = this.length >>> 0, results = Array(length);
+		for (var i = 0; i < length; i++){
+			if (i in this) results[i] = fn.call(bind, this[i], i, this);
+		}
+		return results;
+	},
+
+	some: function(fn, bind){
+		for (var i = 0, l = this.length >>> 0; i < l; i++){
+			if ((i in this) && fn.call(bind, this[i], i, this)) return true;
+		}
+		return false;
+	},
+	/*</!ES5>*/
+
+	clean: function(){
+		return this.filter(function(item){
+			return item != null;
+		});
+	},
+
+	invoke: function(methodName){
+		var args = Array.slice(arguments, 1);
+		return this.map(function(item){
+			return item[methodName].apply(item, args);
+		});
+	},
+
+	associate: function(keys){
+		var obj = {}, length = Math.min(this.length, keys.length);
+		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
+		return obj;
+	},
+
+	link: function(object){
+		var result = {};
+		for (var i = 0, l = this.length; i < l; i++){
+			for (var key in object){
+				if (object[key](this[i])){
+					result[key] = this[i];
+					delete object[key];
+					break;
+				}
+			}
+		}
+		return result;
+	},
+
+	contains: function(item, from){
+		return this.indexOf(item, from) != -1;
+	},
+
+	append: function(array){
+		this.push.apply(this, array);
+		return this;
+	},
+
+	getLast: function(){
+		return (this.length) ? this[this.length - 1] : null;
+	},
+
+	getRandom: function(){
+		return (this.length) ? this[Number.random(0, this.length - 1)] : null;
+	},
+
+	include: function(item){
+		if (!this.contains(item)) this.push(item);
+		return this;
+	},
+
+	combine: function(array){
+		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
+		return this;
+	},
+
+	erase: function(item){
+		for (var i = this.length; i--;){
+			if (this[i] === item) this.splice(i, 1);
+		}
+		return this;
+	},
+
+	empty: function(){
+		this.length = 0;
+		return this;
+	},
+
+	flatten: function(){
+		var array = [];
+		for (var i = 0, l = this.length; i < l; i++){
+			var type = typeOf(this[i]);
+			if (type == 'null') continue;
+			array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
+		}
+		return array;
+	},
+
+	pick: function(){
+		for (var i = 0, l = this.length; i < l; i++){
+			if (this[i] != null) return this[i];
+		}
+		return null;
+	},
+
+	hexToRgb: function(array){
+		if (this.length != 3) return null;
+		var rgb = this.map(function(value){
+			if (value.length == 1) value += value;
+			return parseInt(value, 16);
+		});
+		return (array) ? rgb : 'rgb(' + rgb + ')';
+	},
+
+	rgbToHex: function(array){
+		if (this.length < 3) return null;
+		if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
+		var hex = [];
+		for (var i = 0; i < 3; i++){
+			var bit = (this[i] - 0).toString(16);
+			hex.push((bit.length == 1) ? '0' + bit : bit);
+		}
+		return (array) ? hex : '#' + hex.join('');
+	}
+
+});
+
+
+
+
+/*
+---
+
+name: String
+
+description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
+
+license: MIT-style license.
+
+requires: [Type, Array]
+
+provides: String
+
+...
+*/
+
+String.implement({
+
+	//<!ES6>
+	contains: function(string, index){
+		return (index ? String(this).slice(index) : String(this)).indexOf(string) > -1;
+	},
+	//</!ES6>
+
+	test: function(regex, params){
+		return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
+	},
+
+	trim: function(){
+		return String(this).replace(/^\s+|\s+$/g, '');
+	},
+
+	clean: function(){
+		return String(this).replace(/\s+/g, ' ').trim();
+	},
+
+	camelCase: function(){
+		return String(this).replace(/-\D/g, function(match){
+			return match.charAt(1).toUpperCase();
+		});
+	},
+
+	hyphenate: function(){
+		return String(this).replace(/[A-Z]/g, function(match){
+			return ('-' + match.charAt(0).toLowerCase());
+		});
+	},
+
+	capitalize: function(){
+		return String(this).replace(/\b[a-z]/g, function(match){
+			return match.toUpperCase();
+		});
+	},
+
+	escapeRegExp: function(){
+		return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
+	},
+
+	toInt: function(base){
+		return parseInt(this, base || 10);
+	},
+
+	toFloat: function(){
+		return parseFloat(this);
+	},
+
+	hexToRgb: function(array){
+		var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
+		return (hex) ? hex.slice(1).hexToRgb(array) : null;
+	},
+
+	rgbToHex: function(array){
+		var rgb = String(this).match(/\d{1,3}/g);
+		return (rgb) ? rgb.rgbToHex(array) : null;
+	},
+
+	substitute: function(object, regexp){
+		return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
+			if (match.charAt(0) == '\\') return match.slice(1);
+			return (object[name] != null) ? object[name] : '';
+		});
+	}
+
+});
+
+
+
+
+/*
+---
+
+name: Number
+
+description: Contains Number Prototypes like limit, round, times, and ceil.
+
+license: MIT-style license.
+
+requires: Type
+
+provides: Number
+
+...
+*/
+
+Number.implement({
+
+	limit: function(min, max){
+		return Math.min(max, Math.max(min, this));
+	},
+
+	round: function(precision){
+		precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
+		return Math.round(this * precision) / precision;
+	},
+
+	times: function(fn, bind){
+		for (var i = 0; i < this; i++) fn.call(bind, i, this);
+	},
+
+	toFloat: function(){
+		return parseFloat(this);
+	},
+
+	toInt: function(base){
+		return parseInt(this, base || 10);
+	}
+
+});
+
+Number.alias('each', 'times');
+
+(function(math){
+	var methods = {};
+	math.each(function(name){
+		if (!Number[name]) methods[name] = function(){
+			return Math[name].apply(null, [this].concat(Array.from(arguments)));
+		};
+	});
+	Number.implement(methods);
+})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
+
+
+/*
+---
+
+name: Function
+
+description: Contains Function Prototypes like create, bind, pass, and delay.
+
+license: MIT-style license.
+
+requires: Type
+
+provides: Function
+
+...
+*/
+
+Function.extend({
+
+	attempt: function(){
+		for (var i = 0, l = arguments.length; i < l; i++){
+			try {
+				return arguments[i]();
+			} catch (e){}
+		}
+		return null;
+	}
+
+});
+
+Function.implement({
+
+	attempt: function(args, bind){
+		try {
+			return this.apply(bind, Array.from(args));
+		} catch (e){}
+
+		return null;
+	},
+
+	/*<!ES5-bind>*/
+	bind: function(that){
+		var self = this,
+			args = arguments.length > 1 ? Array.slice(arguments, 1) : null,
+			F = function(){};
+
+		var bound = function(){
+			var context = that, length = arguments.length;
+			if (this instanceof bound){
+				F.prototype = self.prototype;
+				context = new F;
+			}
+			var result = (!args && !length)
+				? self.call(context)
+				: self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
+			return context == that ? result : context;
+		};
+		return bound;
+	},
+	/*</!ES5-bind>*/
+
+	pass: function(args, bind){
+		var self = this;
+		if (args != null) args = Array.from(args);
+		return function(){
+			return self.apply(bind, args || arguments);
+		};
+	},
+
+	delay: function(delay, bind, args){
+		return setTimeout(this.pass((args == null ? [] : args), bind), delay);
+	},
+
+	periodical: function(periodical, bind, args){
+		return setInterval(this.pass((args == null ? [] : args), bind), periodical);
+	}
+
+});
+
+
+
+
+/*
+---
+
+name: Object
+
+description: Object generic methods
+
+license: MIT-style license.
+
+requires: Type
+
+provides: [Object, Hash]
+
+...
+*/
+
+(function(){
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+Object.extend({
+
+	subset: function(object, keys){
+		var results = {};
+		for (var i = 0, l = keys.length; i < l; i++){
+			var k = keys[i];
+			if (k in object) results[k] = object[k];
+		}
+		return results;
+	},
+
+	map: function(object, fn, bind){
+		var results = {};
+		for (var key in object){
+			if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);
+		}
+		return results;
+	},
+
+	filter: function(object, fn, bind){
+		var results = {};
+		for (var key in object){
+			var value = object[key];
+			if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value;
+		}
+		return results;
+	},
+
+	every: function(object, fn, bind){
+		for (var key in object){
+			if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;
+		}
+		return true;
+	},
+
+	some: function(object, fn, bind){
+		for (var key in object){
+			if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true;
+		}
+		return false;
+	},
+
+	keys: function(object){
+		var keys = [];
+		for (var key in object){
+			if (hasOwnProperty.call(object, key)) keys.push(key);
+		}
+		return keys;
+	},
+
+	values: function(object){
+		var values = [];
+		for (var key in object){
+			if (hasOwnProperty.call(object, key)) values.push(object[key]);
+		}
+		return values;
+	},
+
+	getLength: function(object){
+		return Object.keys(object).length;
+	},
+
+	keyOf: function(object, value){
+		for (var key in object){
+			if (hasOwnProperty.call(object, key) && object[key] === value) return key;
+		}
+		return null;
+	},
+
+	contains: function(object, value){
+		return Object.keyOf(object, value) != null;
+	},
+
+	toQueryString: function(object, base){
+		var queryString = [];
+
+		Object.each(object, function(value, key){
+			if (base) key = base + '[' + key + ']';
+			var result;
+			switch (typeOf(value)){
+				case 'object': result = Object.toQueryString(value, key); break;
+				case 'array':
+					var qs = {};
+					value.each(function(val, i){
+						qs[i] = val;
+					});
+					result = Object.toQueryString(qs, key);
+				break;
+				default: result = key + '=' + encodeURIComponent(value);
+			}
+			if (value != null) queryString.push(result);
+		});
+
+		return queryString.join('&');
+	}
+
+});
+
+})();
+
+
+
+
+/*
+---
+
+name: Browser
+
+description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
+
+license: MIT-style license.
+
+requires: [Array, Function, Number, String]
+
+provides: [Browser, Window, Document]
+
+...
+*/
+
+(function(){
+
+var document = this.document;
+var window = document.window = this;
+
+var parse = function(ua, platform){
+	ua = ua.toLowerCase();
+	platform = (platform ? platform.toLowerCase() : '');
+
+	var UA = ua.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/) || [null, 'unknown', 0];
+
+	if (UA[1] == 'trident'){
+		UA[1] = 'ie';
+		if (UA[4]) UA[2] = UA[4];
+	} else if (UA[1] == 'crios') {
+		UA[1] = 'chrome';
+	}
+
+	var platform = ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0];
+	if (platform == 'win') platform = 'windows';
+
+	return {
+		extend: Function.prototype.extend,
+		name: (UA[1] == 'version') ? UA[3] : UA[1],
+		version: parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
+		platform: platform
+	};
+};
+
+var Browser = this.Browser = parse(navigator.userAgent, navigator.platform);
+
+if (Browser.ie){
+	Browser.version = document.documentMode;
+}
+
+Browser.extend({
+	Features: {
+		xpath: !!(document.evaluate),
+		air: !!(window.runtime),
+		query: !!(document.querySelector),
+		json: !!(window.JSON)
+	},
+	parseUA: parse
+});
+
+
+
+// Request
+
+Browser.Request = (function(){
+
+	var XMLHTTP = function(){
+		return new XMLHttpRequest();
+	};
+
+	var MSXML2 = function(){
+		return new ActiveXObject('MSXML2.XMLHTTP');
+	};
+
+	var MSXML = function(){
+		return new ActiveXObject('Microsoft.XMLHTTP');
+	};
+
+	return Function.attempt(function(){
+		XMLHTTP();
+		return XMLHTTP;
+	}, function(){
+		MSXML2();
+		return MSXML2;
+	}, function(){
+		MSXML();
+		return MSXML;
+	});
+
+})();
+
+Browser.Features.xhr = !!(Browser.Request);
+
+
+
+// String scripts
+
+Browser.exec = function(text){
+	if (!text) return text;
+	if (window.execScript){
+		window.execScript(text);
+	} else {
+		var script = document.createElement('script');
+		script.setAttribute('type', 'text/javascript');
+		script.text = text;
+		document.head.appendChild(script);
+		document.head.removeChild(script);
+	}
+	return text;
+};
+
+String.implement('stripScripts', function(exec){
+	var scripts = '';
+	var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
+		scripts += code + '\n';
+		return '';
+	});
+	if (exec === true) Browser.exec(scripts);
+	else if (typeOf(exec) == 'function') exec(scripts, text);
+	return text;
+});
+
+// Window, Document
+
+Browser.extend({
+	Document: this.Document,
+	Window: this.Window,
+	Element: this.Element,
+	Event: this.Event
+});
+
+this.Window = this.$constructor = new Type('Window', function(){});
+
+this.$family = Function.from('window').hide();
+
+Window.mirror(function(name, method){
+	window[name] = method;
+});
+
+this.Document = document.$constructor = new Type('Document', function(){});
+
+document.$family = Function.from('document').hide();
+
+Document.mirror(function(name, method){
+	document[name] = method;
+});
+
+document.html = document.documentElement;
+if (!document.head) document.head = document.getElementsByTagName('head')[0];
+
+if (document.execCommand) try {
+	document.execCommand("BackgroundImageCache", false, true);
+} catch (e){}
+
+/*<ltIE9>*/
+if (this.attachEvent && !this.addEventListener){
+	var unloadEvent = function(){
+		this.detachEvent('onunload', unloadEvent);
+		document.head = document.html = document.window = null;
+	};
+	this.attachEvent('onunload', unloadEvent);
+}
+
+// IE fails on collections and <select>.options (refers to <select>)
+var arrayFrom = Array.from;
+try {
+	arrayFrom(document.html.childNodes);
+} catch(e){
+	Array.from = function(item){
+		if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
+			var i = item.length, array = new Array(i);
+			while (i--) array[i] = item[i];
+			return array;
+		}
+		return arrayFrom(item);
+	};
+
+	var prototype = Array.prototype,
+		slice = prototype.slice;
+	['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
+		var method = prototype[name];
+		Array[name] = function(item){
+			return method.apply(Array.from(item), slice.call(arguments, 1));
+		};
+	});
+}
+/*</ltIE9>*/
+
+
+
+})();
+
+
+/*
+---
+
+name: Event
+
+description: Contains the Event Type, to make the event object cross-browser.
+
+license: MIT-style license.
+
+requires: [Window, Document, Array, Function, String, Object]
+
+provides: Event
+
+...
+*/
+
+(function() {
+
+var _keys = {};
+
+var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){
+	if (!win) win = window;
+	event = event || win.event;
+	if (event.$extended) return event;
+	this.event = event;
+	this.$extended = true;
+	this.shift = event.shiftKey;
+	this.control = event.ctrlKey;
+	this.alt = event.altKey;
+	this.meta = event.metaKey;
+	var type = this.type = event.type;
+	var target = event.target || event.srcElement;
+	while (target && target.nodeType == 3) target = target.parentNode;
+	this.target = document.id(target);
+
+	if (type.indexOf('key') == 0){
+		var code = this.code = (event.which || event.keyCode);
+		this.key = _keys[code];
+		if (type == 'keydown' || type == 'keyup'){
+			if (code > 111 && code < 124) this.key = 'f' + (code - 111);
+			else if (code > 95 && code < 106) this.key = code - 96;
+		}
+		if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
+	} else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){
+		var doc = win.document;
+		doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
+		this.page = {
+			x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
+			y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
+		};
+		this.client = {
+			x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
+			y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
+		};
+		if (type == 'DOMMouseScroll' || type == 'mousewheel')
+			this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
+
+		this.rightClick = (event.which == 3 || event.button == 2);
+		if (type == 'mouseover' || type == 'mouseout'){
+			var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
+			while (related && related.nodeType == 3) related = related.parentNode;
+			this.relatedTarget = document.id(related);
+		}
+	} else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){
+		this.rotation = event.rotation;
+		this.scale = event.scale;
+		this.targetTouches = event.targetTouches;
+		this.changedTouches = event.changedTouches;
+		var touches = this.touches = event.touches;
+		if (touches && touches[0]){
+			var touch = touches[0];
+			this.page = {x: touch.pageX, y: touch.pageY};
+			this.client = {x: touch.clientX, y: touch.clientY};
+		}
+	}
+
+	if (!this.client) this.client = {};
+	if (!this.page) this.page = {};
+});
+
+DOMEvent.implement({
+
+	stop: function(){
+		return this.preventDefault().stopPropagation();
+	},
+
+	stopPropagation: function(){
+		if (this.event.stopPropagation) this.event.stopPropagation();
+		else this.event.cancelBubble = true;
+		return this;
+	},
+
+	preventDefault: function(){
+		if (this.event.preventDefault) this.event.preventDefault();
+		else this.event.returnValue = false;
+		return this;
+	}
+
+});
+
+DOMEvent.defineKey = function(code, key){
+	_keys[code] = key;
+	return this;
+};
+
+DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
+
+DOMEvent.defineKeys({
+	'38': 'up', '40': 'down', '37': 'left', '39': 'right',
+	'27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab',
+	'46': 'delete', '13': 'enter'
+});
+
+})();
+
+
+
+
+
+
+/*
+---
+
+name: Class
+
+description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
+
+license: MIT-style license.
+
+requires: [Array, String, Function, Number]
+
+provides: Class
+
+...
+*/
+
+(function(){
+
+var Class = this.Class = new Type('Class', function(params){
+	if (instanceOf(params, Function)) params = {initialize: params};
+
+	var newClass = function(){
+		reset(this);
+		if (newClass.$prototyping) return this;
+		this.$caller = null;
+		var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
+		this.$caller = this.caller = null;
+		return value;
+	}.extend(this).implement(params);
+
+	newClass.$constructor = Class;
+	newClass.prototype.$constructor = newClass;
+	newClass.prototype.parent = parent;
+
+	return newClass;
+});
+
+var parent = function(){
+	if (!this.$caller) throw new Error('The method "parent" cannot be called.');
+	var name = this.$caller.$name,
+		parent = this.$caller.$owner.parent,
+		previous = (parent) ? parent.prototype[name] : null;
+	if (!previous) throw new Error('The method "' + name + '" has no parent.');
+	return previous.apply(this, arguments);
+};
+
+var reset = function(object){
+	for (var key in object){
+		var value = object[key];
+		switch (typeOf(value)){
+			case 'object':
+				var F = function(){};
+				F.prototype = value;
+				object[key] = reset(new F);
+			break;
+			case 'array': object[key] = value.clone(); break;
+		}
+	}
+	return object;
+};
+
+var wrap = function(self, key, method){
+	if (method.$origin) method = method.$origin;
+	var wrapper = function(){
+		if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
+		var caller = this.caller, current = this.$caller;
+		this.caller = current; this.$caller = wrapper;
+		var result = method.apply(this, arguments);
+		this.$caller = current; this.caller = caller;
+		return result;
+	}.extend({$owner: self, $origin: method, $name: key});
+	return wrapper;
+};
+
+var implement = function(key, value, retain){
+	if (Class.Mutators.hasOwnProperty(key)){
+		value = Class.Mutators[key].call(this, value);
+		if (value == null) return this;
+	}
+
+	if (typeOf(value) == 'function'){
+		if (value.$hidden) return this;
+		this.prototype[key] = (retain) ? value : wrap(this, key, value);
+	} else {
+		Object.merge(this.prototype, key, value);
+	}
+
+	return this;
+};
+
+var getInstance = function(klass){
+	klass.$prototyping = true;
+	var proto = new klass;
+	delete klass.$prototyping;
+	return proto;
+};
+
+Class.implement('implement', implement.overloadSetter());
+
+Class.Mutators = {
+
+	Extends: function(parent){
+		this.parent = parent;
+		this.prototype = getInstance(parent);
+	},
+
+	Implements: function(items){
+		Array.from(items).each(function(item){
+			var instance = new item;
+			for (var key in instance) implement.call(this, key, instance[key], true);
+		}, this);
+	}
+};
+
+})();
+
+
+/*
+---
+
+name: Class.Extras
+
+description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
+
+license: MIT-style license.
+
+requires: Class
+
+provides: [Class.Extras, Chain, Events, Options]
+
+...
+*/
+
+(function(){
+
+this.Chain = new Class({
+
+	$chain: [],
+
+	chain: function(){
+		this.$chain.append(Array.flatten(arguments));
+		return this;
+	},
+
+	callChain: function(){
+		return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
+	},
+
+	clearChain: function(){
+		this.$chain.empty();
+		return this;
+	}
+
+});
+
+var removeOn = function(string){
+	return string.replace(/^on([A-Z])/, function(full, first){
+		return first.toLowerCase();
+	});
+};
+
+this.Events = new Class({
+
+	$events: {},
+
+	addEvent: function(type, fn, internal){
+		type = removeOn(type);
+
+		
+
+		this.$events[type] = (this.$events[type] || []).include(fn);
+		if (internal) fn.internal = true;
+		return this;
+	},
+
+	addEvents: function(events){
+		for (var type in events) this.addEvent(type, events[type]);
+		return this;
+	},
+
+	fireEvent: function(type, args, delay){
+		type = removeOn(type);
+		var events = this.$events[type];
+		if (!events) return this;
+		args = Array.from(args);
+		events.each(function(fn){
+			if (delay) fn.delay(delay, this, args);
+			else fn.apply(this, args);
+		}, this);
+		return this;
+	},
+
+	removeEvent: function(type, fn){
+		type = removeOn(type);
+		var events = this.$events[type];
+		if (events && !fn.internal){
+			var index =  events.indexOf(fn);
+			if (index != -1) delete events[index];
+		}
+		return this;
+	},
+
+	removeEvents: function(events){
+		var type;
+		if (typeOf(events) == 'object'){
+			for (type in events) this.removeEvent(type, events[type]);
+			return this;
+		}
+		if (events) events = removeOn(events);
+		for (type in this.$events){
+			if (events && events != type) continue;
+			var fns = this.$events[type];
+			for (var i = fns.length; i--;) if (i in fns){
+				this.removeEvent(type, fns[i]);
+			}
+		}
+		return this;
+	}
+
+});
+
+this.Options = new Class({
+
+	setOptions: function(){
+		var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
+		if (this.addEvent) for (var option in options){
+			if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
+			this.addEvent(option, options[option]);
+			delete options[option];
+		}
+		return this;
+	}
+
+});
+
+})();
+
+
+/*
+---
+name: Slick.Parser
+description: Standalone CSS3 Selector parser
+provides: Slick.Parser
+...
+*/
+
+;(function(){
+
+var parsed,
+	separatorIndex,
+	combinatorIndex,
+	reversed,
+	cache = {},
+	reverseCache = {},
+	reUnescape = /\\/g;
+
+var parse = function(expression, isReversed){
+	if (expression == null) return null;
+	if (expression.Slick === true) return expression;
+	expression = ('' + expression).replace(/^\s+|\s+$/g, '');
+	reversed = !!isReversed;
+	var currentCache = (reversed) ? reverseCache : cache;
+	if (currentCache[expression]) return currentCache[expression];
+	parsed = {
+		Slick: true,
+		expressions: [],
+		raw: expression,
+		reverse: function(){
+			return parse(this.raw, true);
+		}
+	};
+	separatorIndex = -1;
+	while (expression != (expression = expression.replace(regexp, parser)));
+	parsed.length = parsed.expressions.length;
+	return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed;
+};
+
+var reverseCombinator = function(combinator){
+	if (combinator === '!') return ' ';
+	else if (combinator === ' ') return '!';
+	else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
+	else return '!' + combinator;
+};
+
+var reverse = function(expression){
+	var expressions = expression.expressions;
+	for (var i = 0; i < expressions.length; i++){
+		var exp = expressions[i];
+		var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};
+
+		for (var j = 0; j < exp.length; j++){
+			var cexp = exp[j];
+			if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
+			cexp.combinator = cexp.reverseCombinator;
+			delete cexp.reverseCombinator;
+		}
+
+		exp.reverse().push(last);
+	}
+	return expression;
+};
+
+var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
+	return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){
+		return '\\' + match;
+	});
+};
+
+var regexp = new RegExp(
+/*
+#!/usr/bin/env ruby
+puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
+__END__
+	"(?x)^(?:\
+	  \\s* ( , ) \\s*               # Separator          \n\
+	| \\s* ( <combinator>+ ) \\s*   # Combinator         \n\
+	|      ( \\s+ )                 # CombinatorChildren \n\
+	|      ( <unicode>+ | \\* )     # Tag                \n\
+	| \\#  ( <unicode>+       )     # ID                 \n\
+	| \\.  ( <unicode>+       )     # ClassName          \n\
+	|                               # Attribute          \n\
+	\\[  \
+		\\s* (<unicode1>+)  (?:  \
+			\\s* ([*^$!~|]?=)  (?:  \
+				\\s* (?:\
+					([\"']?)(.*?)\\9 \
+				)\
+			)  \
+		)?  \\s*  \
+	\\](?!\\]) \n\
+	|   :+ ( <unicode>+ )(?:\
+	\\( (?:\
+		(?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
+	) \\)\
+	)?\
+	)"
+*/
+	"^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
+	.replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
+	.replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
+	.replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
+);
+
+function parser(
+	rawMatch,
+
+	separator,
+	combinator,
+	combinatorChildren,
+
+	tagName,
+	id,
+	className,
+
+	attributeKey,
+	attributeOperator,
+	attributeQuote,
+	attributeValue,
+
+	pseudoMarker,
+	pseudoClass,
+	pseudoQuote,
+	pseudoClassQuotedValue,
+	pseudoClassValue
+){
+	if (separator || separatorIndex === -1){
+		parsed.expressions[++separatorIndex] = [];
+		combinatorIndex = -1;
+		if (separator) return '';
+	}
+
+	if (combinator || combinatorChildren || combinatorIndex === -1){
+		combinator = combinator || ' ';
+		var currentSeparator = parsed.expressions[separatorIndex];
+		if (reversed && currentSeparator[combinatorIndex])
+			currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
+		currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
+	}
+
+	var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
+
+	if (tagName){
+		currentParsed.tag = tagName.replace(reUnescape, '');
+
+	} else if (id){
+		currentParsed.id = id.replace(reUnescape, '');
+
+	} else if (className){
+		className = className.replace(reUnescape, '');
+
+		if (!currentParsed.classList) currentParsed.classList = [];
+		if (!currentParsed.classes) currentParsed.classes = [];
+		currentParsed.classList.push(className);
+		currentParsed.classes.push({
+			value: className,
+			regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
+		});
+
+	} else if (pseudoClass){
+		pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
+		pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
+
+		if (!currentParsed.pseudos) currentParsed.pseudos = [];
+		currentParsed.pseudos.push({
+			key: pseudoClass.replace(reUnescape, ''),
+			value: pseudoClassValue,
+			type: pseudoMarker.length == 1 ? 'class' : 'element'
+		});
+
+	} else if (attributeKey){
+		attributeKey = attributeKey.replace(reUnescape, '');
+		attributeValue = (attributeValue || '').replace(reUnescape, '');
+
+		var test, regexp;
+
+		switch (attributeOperator){
+			case '^=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue)            ); break;
+			case '$=' : regexp = new RegExp(            escapeRegExp(attributeValue) +'$'       ); break;
+			case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
+			case '|=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue) +'(-|$)'   ); break;
+			case  '=' : test = function(value){
+				return attributeValue == value;
+			}; break;
+			case '*=' : test = function(value){
+				return value && value.indexOf(attributeValue) > -1;
+			}; break;
+			case '!=' : test = function(value){
+				return attributeValue != value;
+			}; break;
+			default   : test = function(value){
+				return !!value;
+			};
+		}
+
+		if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
+			return false;
+		};
+
+		if (!test) test = function(value){
+			return value && regexp.test(value);
+		};
+
+		if (!currentParsed.attributes) currentParsed.attributes = [];
+		currentParsed.attributes.push({
+			key: attributeKey,
+			operator: attributeOperator,
+			value: attributeValue,
+			test: test
+		});
+
+	}
+
+	return '';
+};
+
+// Slick NS
+
+var Slick = (this.Slick || {});
+
+Slick.parse = function(expression){
+	return parse(expression);
+};
+
+Slick.escapeRegExp = escapeRegExp;
+
+if (!this.Slick) this.Slick = Slick;
+
+}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
+
+
+/*
+---
+name: Slick.Finder
+description: The new, superfast css selector engine.
+provides: Slick.Finder
+requires: Slick.Parser
+...
+*/
+
+;(function(){
+
+var local = {},
+	featuresCache = {},
+	toString = Object.prototype.toString;
+
+// Feature / Bug detection
+
+local.isNativeCode = function(fn){
+	return (/\{\s*\[native code\]\s*\}/).test('' + fn);
+};
+
+local.isXML = function(document){
+	return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') ||
+	(document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
+};
+
+local.setDocument = function(document){
+
+	// convert elements / window arguments to document. if document cannot be extrapolated, the function returns.
+	var nodeType = document.nodeType;
+	if (nodeType == 9); // document
+	else if (nodeType) document = document.ownerDocument; // node
+	else if (document.navigator) document = document.document; // window
+	else return;
+
+	// check if it's the old document
+
+	if (this.document === document) return;
+	this.document = document;
+
+	// check if we have done feature detection on this document before
+
+	var root = document.documentElement,
+		rootUid = this.getUIDXML(root),
+		features = featuresCache[rootUid],
+		feature;
+
+	if (features){
+		for (feature in features){
+			this[feature] = features[feature];
+		}
+		return;
+	}
+
+	features = featuresCache[rootUid] = {};
+
+	features.root = root;
+	features.isXMLDocument = this.isXML(document);
+
+	features.brokenStarGEBTN
+	= features.starSelectsClosedQSA
+	= features.idGetsName
+	= features.brokenMixedCaseQSA
+	= features.brokenGEBCN
+	= features.brokenCheckedQSA
+	= features.brokenEmptyAttributeQSA
+	= features.isHTMLDocument
+	= features.nativeMatchesSelector
+	= false;
+
+	var starSelectsClosed, starSelectsComments,
+		brokenSecondClassNameGEBCN, cachedGetElementsByClassName,
+		brokenFormAttributeGetter;
+
+	var selected, id = 'slick_uniqueid';
+	var testNode = document.createElement('div');
+
+	var testRoot = document.body || document.getElementsByTagName('body')[0] || root;
+	testRoot.appendChild(testNode);
+
+	// on non-HTML documents innerHTML and getElementsById doesnt work properly
+	try {
+		testNode.innerHTML = '<a id="'+id+'"></a>';
+		features.isHTMLDocument = !!document.getElementById(id);
+	} catch(e){};
+
+	if (features.isHTMLDocument){
+
+		testNode.style.display = 'none';
+
+		// IE returns comment nodes for getElementsByTagName('*') for some documents
+		testNode.appendChild(document.createComment(''));
+		starSelectsComments = (testNode.getElementsByTagName('*').length > 1);
+
+		// IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents
+		try {
+			testNode.innerHTML = 'foo</foo>';
+			selected = testNode.getElementsByTagName('*');
+			starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
+		} catch(e){};
+
+		features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
+
+		// IE returns elements with the name instead of just id for getElementsById for some documents
+		try {
+			testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>';
+			features.idGetsName = document.getElementById(id) === testNode.firstChild;
+		} catch(e){};
+
+		if (testNode.getElementsByClassName){
+
+			// Safari 3.2 getElementsByClassName caches results
+			try {
+				testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
+				testNode.getElementsByClassName('b').length;
+				testNode.firstChild.className = 'b';
+				cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2);
+			} catch(e){};
+
+			// Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one
+			try {
+				testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
+				brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2);
+			} catch(e){};
+
+			features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;
+		}
+
+		if (testNode.querySelectorAll){
+			// IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents
+			try {
+				testNode.innerHTML = 'foo</foo>';
+				selected = testNode.querySelectorAll('*');
+				features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
+			} catch(e){};
+
+			// Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode
+			try {
+				testNode.innerHTML = '<a class="MiX"></a>';
+				features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length;
+			} catch(e){};
+
+			// Webkit and Opera dont return selected options on querySelectorAll
+			try {
+				testNode.innerHTML = '<select><option selected="selected">a</option></select>';
+				features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
+			} catch(e){};
+
+			// IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
+			try {
+				testNode.innerHTML = '<a class=""></a>';
+				features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
+			} catch(e){};
+
+		}
+
+		// IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input
+		try {
+			testNode.innerHTML = '<form action="s"><input id="action"/></form>';
+			brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's');
+		} catch(e){};
+
+		// native matchesSelector function
+
+		features.nativeMatchesSelector = root.matches || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector;
+		if (features.nativeMatchesSelector) try {
+			// if matchesSelector trows errors on incorrect sintaxes we can use it
+			features.nativeMatchesSelector.call(root, ':slick');
+			features.nativeMatchesSelector = null;
+		} catch(e){};
+
+	}
+
+	try {
+		root.slick_expando = 1;
+		delete root.slick_expando;
+		features.getUID = this.getUIDHTML;
+	} catch(e) {
+		features.getUID = this.getUIDXML;
+	}
+
+	testRoot.removeChild(testNode);
+	testNode = selected = testRoot = null;
+
+	// getAttribute
+
+	features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){
+		var method = this.attributeGetters[name];
+		if (method) return method.call(node);
+		var attributeNode = node.getAttributeNode(name);
+		return (attributeNode) ? attributeNode.nodeValue : null;
+	} : function(node, name){
+		var method = this.attributeGetters[name];
+		return (method) ? method.call(node) : node.getAttribute(name);
+	};
+
+	// hasAttribute
+
+	features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) {
+		return node.hasAttribute(attribute);
+	} : function(node, attribute) {
+		node = node.getAttributeNode(attribute);
+		return !!(node && (node.specified || node.nodeValue));
+	};
+
+	// contains
+	// FIXME: Add specs: local.contains should be different for xml and html documents?
+	var nativeRootContains = root && this.isNativeCode(root.contains),
+		nativeDocumentContains = document && this.isNativeCode(document.contains);
+
+	features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){
+		return context.contains(node);
+	} : (nativeRootContains && !nativeDocumentContains) ? function(context, node){
+		// IE8 does not have .contains on document.
+		return context === node || ((context === document) ? document.documentElement : context).contains(node);
+	} : (root && root.compareDocumentPosition) ? function(context, node){
+		return context === node || !!(context.compareDocumentPosition(node) & 16);
+	} : function(context, node){
+		if (node) do {
+			if (node === context) return true;
+		} while ((node = node.parentNode));
+		return false;
+	};
+
+	// document order sorting
+	// credits to Sizzle (http://sizzlejs.com/)
+
+	features.documentSorter = (root.compareDocumentPosition) ? function(a, b){
+		if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
+		return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
+	} : ('sourceIndex' in root) ? function(a, b){
+		if (!a.sourceIndex || !b.sourceIndex) return 0;
+		return a.sourceIndex - b.sourceIndex;
+	} : (document.createRange) ? function(a, b){
+		if (!a.ownerDocument || !b.ownerDocument) return 0;
+		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
+		aRange.setStart(a, 0);
+		aRange.setEnd(a, 0);
+		bRange.setStart(b, 0);
+		bRange.setEnd(b, 0);
+		return aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
+	} : null ;
+
+	root = null;
+
+	for (feature in features){
+		this[feature] = features[feature];
+	}
+};
+
+// Main Method
+
+var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/,
+	reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/,
+	qsaFailExpCache = {};
+
+local.search = function(context, expression, append, first){
+
+	var found = this.found = (first) ? null : (append || []);
+
+	if (!context) return found;
+	else if (context.navigator) context = context.document; // Convert the node from a window to a document
+	else if (!context.nodeType) return found;
+
+	// setup
+
+	var parsed, i,
+		uniques = this.uniques = {},
+		hasOthers = !!(append && append.length),
+		contextIsDocument = (context.nodeType == 9);
+
+	if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);
+
+	// avoid duplicating items already in the append array
+	if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true;
+
+	// expression checks
+
+	if (typeof expression == 'string'){ // expression is a string
+
+		/*<simple-selectors-override>*/
+		var simpleSelector = expression.match(reSimpleSelector);
+		simpleSelectors: if (simpleSelector) {
+
+			var symbol = simpleSelector[1],
+				name = simpleSelector[2],
+				node, nodes;
+
+			if (!symbol){
+
+				if (name == '*' && this.brokenStarGEBTN) break simpleSelectors;
+				nodes = context.getElementsByTagName(name);
+				if (first) return nodes[0] || null;
+				for (i = 0; node = nodes[i++];){
+					if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
+				}
+
+			} else if (symbol == '#'){
+
+				if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors;
+				node = context.getElementById(name);
+				if (!node) return found;
+				if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors;
+				if (first) return node || null;
+				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
+
+			} else if (symbol == '.'){
+
+				if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors;
+				if (context.getElementsByClassName && !this.brokenGEBCN){
+					nodes = context.getElementsByClassName(name);
+					if (first) return nodes[0] || null;
+					for (i = 0; node = nodes[i++];){
+						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
+					}
+				} else {
+					var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)');
+					nodes = context.getElementsByTagName('*');
+					for (i = 0; node = nodes[i++];){
+						className = node.className;
+						if (!(className && matchClass.test(className))) continue;
+						if (first) return node;
+						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
+					}
+				}
+
+			}
+
+			if (hasOthers) this.sort(found);
+			return (first) ? null : found;
+
+		}
+		/*</simple-selectors-override>*/
+
+		/*<query-selector-override>*/
+		querySelector: if (context.querySelectorAll) {
+
+			if (!this.isHTMLDocument
+				|| qsaFailExpCache[expression]
+				//TODO: only skip when expression is actually mixed case
+				|| this.brokenMixedCaseQSA
+				|| (this.brokenCheckedQSA && expression.indexOf(':checked') > -1)
+				|| (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression))
+				|| (!contextIsDocument //Abort when !contextIsDocument and...
+					//  there are multiple expressions in the selector
+					//  since we currently only fix non-document rooted QSA for single expression selectors
+					&& expression.indexOf(',') > -1
+				)
+				|| Slick.disableQSA
+			) break querySelector;
+
+			var _expression = expression, _context = context;
+			if (!contextIsDocument){
+				// non-document rooted QSA
+				// credits to Andrew Dupont
+				var currentId = _context.getAttribute('id'), slickid = 'slickid__';
+				_context.setAttribute('id', slickid);
+				_expression = '#' + slickid + ' ' + _expression;
+				context = _context.parentNode;
+			}
+
+			try {
+				if (first) return context.querySelector(_expression) || null;
+				else nodes = context.querySelectorAll(_expression);
+			} catch(e) {
+				qsaFailExpCache[expression] = 1;
+				break querySelector;
+			} finally {
+				if (!contextIsDocument){
+					if (currentId) _context.setAttribute('id', currentId);
+					else _context.removeAttribute('id');
+					context = _context;
+				}
+			}
+
+			if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){
+				if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node);
+			} else for (i = 0; node = nodes[i++];){
+				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
+			}
+
+			if (hasOthers) this.sort(found);
+			return found;
+
+		}
+		/*</query-selector-override>*/
+
+		parsed = this.Slick.parse(expression);
+		if (!parsed.length) return found;
+	} else if (expression == null){ // there is no expression
+		return found;
+	} else if (expression.Slick){ // expression is a parsed Slick object
+		parsed = expression;
+	} else if (this.contains(context.documentElement || context, expression)){ // expression is a node
+		(found) ? found.push(expression) : found = expression;
+		return found;
+	} else { // other junk
+		return found;
+	}
+
+	/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
+
+	// cache elements for the nth selectors
+
+	this.posNTH = {};
+	this.posNTHLast = {};
+	this.posNTHType = {};
+	this.posNTHTypeLast = {};
+
+	/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
+
+	// if append is null and there is only a single selector with one expression use pushArray, else use pushUID
+	this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;
+
+	if (found == null) found = [];
+
+	// default engine
+
+	var j, m, n;
+	var combinator, tag, id, classList, classes, attributes, pseudos;
+	var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions;
+
+	search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){
+
+		combinator = 'combinator:' + currentBit.combinator;
+		if (!this[combinator]) continue search;
+
+		tag        = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase();
+		id         = currentBit.id;
+		classList  = currentBit.classList;
+		classes    = currentBit.classes;
+		attributes = currentBit.attributes;
+		pseudos    = currentBit.pseudos;
+		lastBit    = (j === (currentExpression.length - 1));
+
+		this.bitUniques = {};
+
+		if (lastBit){
+			this.uniques = uniques;
+			this.found = found;
+		} else {
+			this.uniques = {};
+			this.found = [];
+		}
+
+		if (j === 0){
+			this[combinator](context, tag, id, classes, attributes, pseudos, classList);
+			if (first && lastBit && found.length) break search;
+		} else {
+			if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){
+				this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
+				if (found.length) break search;
+			} else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
+		}
+
+		currentItems = this.found;
+	}
+
+	// should sort if there are nodes in append and if you pass multiple expressions.
+	if (hasOthers || (parsed.expressions.length > 1)) this.sort(found);
+
+	return (first) ? (found[0] || null) : found;
+};
+
+// Utils
+
+local.uidx = 1;
+local.uidk = 'slick-uniqueid';
+
+local.getUIDXML = function(node){
+	var uid = node.getAttribute(this.uidk);
+	if (!uid){
+		uid = this.uidx++;
+		node.setAttribute(this.uidk, uid);
+	}
+	return uid;
+};
+
+local.getUIDHTML = function(node){
+	return node.uniqueNumber || (node.uniqueNumber = this.uidx++);
+};
+
+// sort based on the setDocument documentSorter method.
+
+local.sort = function(results){
+	if (!this.documentSorter) return results;
+	results.sort(this.documentSorter);
+	return results;
+};
+
+/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
+
+local.cacheNTH = {};
+
+local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;
+
+local.parseNTHArgument = function(argument){
+	var parsed = argument.match(this.matchNTH);
+	if (!parsed) return false;
+	var special = parsed[2] || false;
+	var a = parsed[1] || 1;
+	if (a == '-') a = -1;
+	var b = +parsed[3] || 0;
+	parsed =
+		(special == 'n')	? {a: a, b: b} :
+		(special == 'odd')	? {a: 2, b: 1} :
+		(special == 'even')	? {a: 2, b: 0} : {a: 0, b: a};
+
+	return (this.cacheNTH[argument] = parsed);
+};
+
+local.createNTHPseudo = function(child, sibling, positions, ofType){
+	return function(node, argument){
+		var uid = this.getUID(node);
+		if (!this[positions][uid]){
+			var parent = node.parentNode;
+			if (!parent) return false;
+			var el = parent[child], count = 1;
+			if (ofType){
+				var nodeName = node.nodeName;
+				do {
+					if (el.nodeName != nodeName) continue;
+					this[positions][this.getUID(el)] = count++;
+				} while ((el = el[sibling]));
+			} else {
+				do {
+					if (el.nodeType != 1) continue;
+					this[positions][this.getUID(el)] = count++;
+				} while ((el = el[sibling]));
+			}
+		}
+		argument = argument || 'n';
+		var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
+		if (!parsed) return false;
+		var a = parsed.a, b = parsed.b, pos = this[positions][uid];
+		if (a == 0) return b == pos;
+		if (a > 0){
+			if (pos < b) return false;
+		} else {
+			if (b < pos) return false;
+		}
+		return ((pos - b) % a) == 0;
+	};
+};
+
+/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
+
+local.pushArray = function(node, tag, id, classes, attributes, pseudos){
+	if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node);
+};
+
+local.pushUID = function(node, tag, id, classes, attributes, pseudos){
+	var uid = this.getUID(node);
+	if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){
+		this.uniques[uid] = true;
+		this.found.push(node);
+	}
+};
+
+local.matchNode = function(node, selector){
+	if (this.isHTMLDocument && this.nativeMatchesSelector){
+		try {
+			return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]'));
+		} catch(matchError) {}
+	}
+
+	var parsed = this.Slick.parse(selector);
+	if (!parsed) return true;
+
+	// simple (single) selectors
+	var expressions = parsed.expressions, simpleExpCounter = 0, i;
+	for (i = 0; (currentExpression = expressions[i]); i++){
+		if (currentExpression.length == 1){
+			var exp = currentExpression[0];
+			if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true;
+			simpleExpCounter++;
+		}
+	}
+
+	if (simpleExpCounter == parsed.length) return false;
+
+	var nodes = this.search(this.document, parsed), item;
+	for (i = 0; item = nodes[i++];){
+		if (item === node) return true;
+	}
+	return false;
+};
+
+local.matchPseudo = function(node, name, argument){
+	var pseudoName = 'pseudo:' + name;
+	if (this[pseudoName]) return this[pseudoName](node, argument);
+	var attribute = this.getAttribute(node, name);
+	return (argument) ? argument == attribute : !!attribute;
+};
+
+local.matchSelector = function(node, tag, id, classes, attributes, pseudos){
+	if (tag){
+		var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase();
+		if (tag == '*'){
+			if (nodeName < '@') return false; // Fix for comment nodes and closed nodes
+		} else {
+			if (nodeName != tag) return false;
+		}
+	}
+
+	if (id && node.getAttribute('id') != id) return false;
+
+	var i, part, cls;
+	if (classes) for (i = classes.length; i--;){
+		cls = this.getAttribute(node, 'class');
+		if (!(cls && classes[i].regexp.test(cls))) return false;
+	}
+	if (attributes) for (i = attributes.length; i--;){
+		part = attributes[i];
+		if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false;
+	}
+	if (pseudos) for (i = pseudos.length; i--;){
+		part = pseudos[i];
+		if (!this.matchPseudo(node, part.key, part.value)) return false;
+	}
+	return true;
+};
+
+var combinators = {
+
+	' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level
+
+		var i, item, children;
+
+		if (this.isHTMLDocument){
+			getById: if (id){
+				item = this.document.getElementById(id);
+				if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){
+					// all[id] returns all the elements with that name or id inside node
+					// if theres just one it will return the element, else it will be a collection
+					children = node.all[id];
+					if (!children) return;
+					if (!children[0]) children = [children];
+					for (i = 0; item = children[i++];){
+						var idNode = item.getAttributeNode('id');
+						if (idNode && idNode.nodeValue == id){
+							this.push(item, tag, null, classes, attributes, pseudos);
+							break;
+						}
+					}
+					return;
+				}
+				if (!item){
+					// if the context is in the dom we return, else we will try GEBTN, breaking the getById label
+					if (this.contains(this.root, node)) return;
+					else break getById;
+				} else if (this.document !== node && !this.contains(node, item)) return;
+				this.push(item, tag, null, classes, attributes, pseudos);
+				return;
+			}
+			getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){
+				children = node.getElementsByClassName(classList.join(' '));
+				if (!(children && children.length)) break getByClass;
+				for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos);
+				return;
+			}
+		}
+		getByTag: {
+			children = node.getElementsByTagName(tag);
+			if (!(children && children.length)) break getByTag;
+			if (!this.brokenStarGEBTN) tag = null;
+			for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos);
+		}
+	},
+
+	'>': function(node, tag, id, classes, attributes, pseudos){ // direct children
+		if ((node = node.firstChild)) do {
+			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
+		} while ((node = node.nextSibling));
+	},
+
+	'+': function(node, tag, id, classes, attributes, pseudos){ // next sibling
+		while ((node = node.nextSibling)) if (node.nodeType == 1){
+			this.push(node, tag, id, classes, attributes, pseudos);
+			break;
+		}
+	},
+
+	'^': function(node, tag, id, classes, attributes, pseudos){ // first child
+		node = node.firstChild;
+		if (node){
+			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
+			else this['combinator:+'](node, tag, id, classes, attributes, pseudos);
+		}
+	},
+
+	'~': function(node, tag, id, classes, attributes, pseudos){ // next siblings
+		while ((node = node.nextSibling)){
+			if (node.nodeType != 1) continue;
+			var uid = this.getUID(node);
+			if (this.bitUniques[uid]) break;
+			this.bitUniques[uid] = true;
+			this.push(node, tag, id, classes, attributes, pseudos);
+		}
+	},
+
+	'++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling
+		this['combinator:+'](node, tag, id, classes, attributes, pseudos);
+		this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
+	},
+
+	'~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings
+		this['combinator:~'](node, tag, id, classes, attributes, pseudos);
+		this['combinator:!~'](node, tag, id, classes, attributes, pseudos);
+	},
+
+	'!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
+		while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
+	},
+
+	'!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level)
+		node = node.parentNode;
+		if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
+	},
+
+	'!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling
+		while ((node = node.previousSibling)) if (node.nodeType == 1){
+			this.push(node, tag, id, classes, attributes, pseudos);
+			break;
+		}
+	},
+
+	'!^': function(node, tag, id, classes, attributes, pseudos){ // last child
+		node = node.lastChild;
+		if (node){
+			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
+			else this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
+		}
+	},
+
+	'!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings
+		while ((node = node.previousSibling)){
+			if (node.nodeType != 1) continue;
+			var uid = this.getUID(node);
+			if (this.bitUniques[uid]) break;
+			this.bitUniques[uid] = true;
+			this.push(node, tag, id, classes, attributes, pseudos);
+		}
+	}
+
+};
+
+for (var c in combinators) local['combinator:' + c] = combinators[c];
+
+var pseudos = {
+
+	/*<pseudo-selectors>*/
+
+	'empty': function(node){
+		var child = node.firstChild;
+		return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length;
+	},
+
+	'not': function(node, expression){
+		return !this.matchNode(node, expression);
+	},
+
+	'contains': function(node, text){
+		return (node.innerText || node.textContent || '').indexOf(text) > -1;
+	},
+
+	'first-child': function(node){
+		while ((node = node.previousSibling)) if (node.nodeType == 1) return false;
+		return true;
+	},
+
+	'last-child': function(node){
+		while ((node = node.nextSibling)) if (node.nodeType == 1) return false;
+		return true;
+	},
+
+	'only-child': function(node){
+		var prev = node;
+		while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false;
+		var next = node;
+		while ((next = next.nextSibling)) if (next.nodeType == 1) return false;
+		return true;
+	},
+
+	/*<nth-pseudo-selectors>*/
+
+	'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),
+
+	'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),
+
+	'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),
+
+	'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),
+
+	'index': function(node, index){
+		return this['pseudo:nth-child'](node, '' + (index + 1));
+	},
+
+	'even': function(node){
+		return this['pseudo:nth-child'](node, '2n');
+	},
+
+	'odd': function(node){
+		return this['pseudo:nth-child'](node, '2n+1');
+	},
+
+	/*</nth-pseudo-selectors>*/
+
+	/*<of-type-pseudo-selectors>*/
+
+	'first-of-type': function(node){
+		var nodeName = node.nodeName;
+		while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false;
+		return true;
+	},
+
+	'last-of-type': function(node){
+		var nodeName = node.nodeName;
+		while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false;
+		return true;
+	},
+
+	'only-of-type': function(node){
+		var prev = node, nodeName = node.nodeName;
+		while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false;
+		var next = node;
+		while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false;
+		return true;
+	},
+
+	/*</of-type-pseudo-selectors>*/
+
+	// custom pseudos
+
+	'enabled': function(node){
+		return !node.disabled;
+	},
+
+	'disabled': function(node){
+		return node.disabled;
+	},
+
+	'checked': function(node){
+		return node.checked || node.selected;
+	},
+
+	'focus': function(node){
+		return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex'));
+	},
+
+	'root': function(node){
+		return (node === this.root);
+	},
+
+	'selected': function(node){
+		return node.selected;
+	}
+
+	/*</pseudo-selectors>*/
+};
+
+for (var p in pseudos) local['pseudo:' + p] = pseudos[p];
+
+// attributes methods
+
+var attributeGetters = local.attributeGetters = {
+
+	'for': function(){
+		return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for');
+	},
+
+	'href': function(){
+		return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href');
+	},
+
+	'style': function(){
+		return (this.style) ? this.style.cssText : this.getAttribute('style');
+	},
+
+	'tabindex': function(){
+		var attributeNode = this.getAttributeNode('tabindex');
+		return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
+	},
+
+	'type': function(){
+		return this.getAttribute('type');
+	},
+
+	'maxlength': function(){
+		var attributeNode = this.getAttributeNode('maxLength');
+		return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
+	}
+
+};
+
+attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength;
+
+// Slick
+
+var Slick = local.Slick = (this.Slick || {});
+
+Slick.version = '1.1.7';
+
+// Slick finder
+
+Slick.search = function(context, expression, append){
+	return local.search(context, expression, append);
+};
+
+Slick.find = function(context, expression){
+	return local.search(context, expression, null, true);
+};
+
+// Slick containment checker
+
+Slick.contains = function(container, node){
+	local.setDocument(container);
+	return local.contains(container, node);
+};
+
+// Slick attribute getter
+
+Slick.getAttribute = function(node, name){
+	local.setDocument(node);
+	return local.getAttribute(node, name);
+};
+
+Slick.hasAttribute = function(node, name){
+	local.setDocument(node);
+	return local.hasAttribute(node, name);
+};
+
+// Slick matcher
+
+Slick.match = function(node, selector){
+	if (!(node && selector)) return false;
+	if (!selector || selector === node) return true;
+	local.setDocument(node);
+	return local.matchNode(node, selector);
+};
+
+// Slick attribute accessor
+
+Slick.defineAttributeGetter = function(name, fn){
+	local.attributeGetters[name] = fn;
+	return this;
+};
+
+Slick.lookupAttributeGetter = function(name){
+	return local.attributeGetters[name];
+};
+
+// Slick pseudo accessor
+
+Slick.definePseudo = function(name, fn){
+	local['pseudo:' + name] = function(node, argument){
+		return fn.call(node, argument);
+	};
+	return this;
+};
+
+Slick.lookupPseudo = function(name){
+	var pseudo = local['pseudo:' + name];
+	if (pseudo) return function(argument){
+		return pseudo.call(this, argument);
+	};
+	return null;
+};
+
+// Slick overrides accessor
+
+Slick.override = function(regexp, fn){
+	local.override(regexp, fn);
+	return this;
+};
+
+Slick.isXML = local.isXML;
+
+Slick.uidOf = function(node){
+	return local.getUIDHTML(node);
+};
+
+if (!this.Slick) this.Slick = Slick;
+
+}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
+
+
+/*
+---
+
+name: Element
+
+description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements.
+
+license: MIT-style license.
+
+requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder]
+
+provides: [Element, Elements, $, $$, IFrame, Selectors]
+
+...
+*/
+
+var Element = this.Element = function(tag, props){
+	var konstructor = Element.Constructors[tag];
+	if (konstructor) return konstructor(props);
+	if (typeof tag != 'string') return document.id(tag).set(props);
+
+	if (!props) props = {};
+
+	if (!(/^[\w-]+$/).test(tag)){
+		var parsed = Slick.parse(tag).expressions[0][0];
+		tag = (parsed.tag == '*') ? 'div' : parsed.tag;
+		if (parsed.id && props.id == null) props.id = parsed.id;
+
+		var attributes = parsed.attributes;
+		if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){
+			attr = attributes[i];
+			if (props[attr.key] != null) continue;
+
+			if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
+			else if (!attr.value && !attr.operator) props[attr.key] = true;
+		}
+
+		if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
+	}
+
+	return document.newElement(tag, props);
+};
+
+
+if (Browser.Element){
+	Element.prototype = Browser.Element.prototype;
+	// IE8 and IE9 require the wrapping.
+	Element.prototype._fireEvent = (function(fireEvent){
+		return function(type, event){
+			return fireEvent.call(this, type, event);
+		};
+	})(Element.prototype.fireEvent);
+}
+
+new Type('Element', Element).mirror(function(name){
+	if (Array.prototype[name]) return;
+
+	var obj = {};
+	obj[name] = function(){
+		var results = [], args = arguments, elements = true;
+		for (var i = 0, l = this.length; i < l; i++){
+			var element = this[i], result = results[i] = element[name].apply(element, args);
+			elements = (elements && typeOf(result) == 'element');
+		}
+		return (elements) ? new Elements(results) : results;
+	};
+
+	Elements.implement(obj);
+});
+
+if (!Browser.Element){
+	Element.parent = Object;
+
+	Element.Prototype = {
+		'$constructor': Element,
+		'$family': Function.from('element').hide()
+	};
+
+	Element.mirror(function(name, method){
+		Element.Prototype[name] = method;
+	});
+}
+
+Element.Constructors = {};
+
+
+
+var IFrame = new Type('IFrame', function(){
+	var params = Array.link(arguments, {
+		properties: Type.isObject,
+		iframe: function(obj){
+			return (obj != null);
+		}
+	});
+
+	var props = params.properties || {}, iframe;
+	if (params.iframe) iframe = document.id(params.iframe);
+	var onload = props.onload || function(){};
+	delete props.onload;
+	props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick();
+	iframe = new Element(iframe || 'iframe', props);
+
+	var onLoad = function(){
+		onload.call(iframe.contentWindow);
+	};
+
+	if (window.frames[props.id]) onLoad();
+	else iframe.addListener('load', onLoad);
+	return iframe;
+});
+
+var Elements = this.Elements = function(nodes){
+	if (nodes && nodes.length){
+		var uniques = {}, node;
+		for (var i = 0; node = nodes[i++];){
+			var uid = Slick.uidOf(node);
+			if (!uniques[uid]){
+				uniques[uid] = true;
+				this.push(node);
+			}
+		}
+	}
+};
+
+Elements.prototype = {length: 0};
+Elements.parent = Array;
+
+new Type('Elements', Elements).implement({
+
+	filter: function(filter, bind){
+		if (!filter) return this;
+		return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){
+			return item.match(filter);
+		} : filter, bind));
+	}.protect(),
+
+	push: function(){
+		var length = this.length;
+		for (var i = 0, l = arguments.length; i < l; i++){
+			var item = document.id(arguments[i]);
+			if (item) this[length++] = item;
+		}
+		return (this.length = length);
+	}.protect(),
+
+	unshift: function(){
+		var items = [];
+		for (var i = 0, l = arguments.length; i < l; i++){
+			var item = document.id(arguments[i]);
+			if (item) items.push(item);
+		}
+		return Array.prototype.unshift.apply(this, items);
+	}.protect(),
+
+	concat: function(){
+		var newElements = new Elements(this);
+		for (var i = 0, l = arguments.length; i < l; i++){
+			var item = arguments[i];
+			if (Type.isEnumerable(item)) newElements.append(item);
+			else newElements.push(item);
+		}
+		return newElements;
+	}.protect(),
+
+	append: function(collection){
+		for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]);
+		return this;
+	}.protect(),
+
+	empty: function(){
+		while (this.length) delete this[--this.length];
+		return this;
+	}.protect()
+
+});
+
+
+
+(function(){
+
+// FF, IE
+var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2};
+
+splice.call(object, 1, 1);
+if (object[1] == 1) Elements.implement('splice', function(){
+	var length = this.length;
+	var result = splice.apply(this, arguments);
+	while (length >= this.length) delete this[length--];
+	return result;
+}.protect());
+
+Array.forEachMethod(function(method, name){
+	Elements.implement(name, method);
+});
+
+Array.mirror(Elements);
+
+/*<ltIE8>*/
+var createElementAcceptsHTML;
+try {
+	createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x');
+} catch (e){}
+
+var escapeQuotes = function(html){
+	return ('' + html).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
+};
+/*</ltIE8>*/
+
+Document.implement({
+
+	newElement: function(tag, props){
+		if (props && props.checked != null) props.defaultChecked = props.checked;
+		/*<ltIE8>*/// Fix for readonly name and type properties in IE < 8
+		if (createElementAcceptsHTML && props){
+			tag = '<' + tag;
+			if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"';
+			if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"';
+			tag += '>';
+			delete props.name;
+			delete props.type;
+		}
+		/*</ltIE8>*/
+		return this.id(this.createElement(tag)).set(props);
+	}
+
+});
+
+})();
+
+(function(){
+
+Slick.uidOf(window);
+Slick.uidOf(document);
+
+Document.implement({
+
+	newTextNode: function(text){
+		return this.createTextNode(text);
+	},
+
+	getDocument: function(){
+		return this;
+	},
+
+	getWindow: function(){
+		return this.window;
+	},
+
+	id: (function(){
+
+		var types = {
+
+			string: function(id, nocash, doc){
+				id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1'));
+				return (id) ? types.element(id, nocash) : null;
+			},
+
+			element: function(el, nocash){
+				Slick.uidOf(el);
+				if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){
+					var fireEvent = el.fireEvent;
+					// wrapping needed in IE7, or else crash
+					el._fireEvent = function(type, event){
+						return fireEvent(type, event);
+					};
+					Object.append(el, Element.Prototype);
+				}
+				return el;
+			},
+
+			object: function(obj, nocash, doc){
+				if (obj.toElement) return types.element(obj.toElement(doc), nocash);
+				return null;
+			}
+
+		};
+
+		types.textnode = types.whitespace = types.window = types.document = function(zero){
+			return zero;
+		};
+
+		return function(el, nocash, doc){
+			if (el && el.$family && el.uniqueNumber) return el;
+			var type = typeOf(el);
+			return (types[type]) ? types[type](el, nocash, doc || document) : null;
+		};
+
+	})()
+
+});
+
+if (window.$ == null) Window.implement('$', function(el, nc){
+	return document.id(el, nc, this.document);
+});
+
+Window.implement({
+
+	getDocument: function(){
+		return this.document;
+	},
+
+	getWindow: function(){
+		return this;
+	}
+
+});
+
+[Document, Element].invoke('implement', {
+
+	getElements: function(expression){
+		return Slick.search(this, expression, new Elements);
+	},
+
+	getElement: function(expression){
+		return document.id(Slick.find(this, expression));
+	}
+
+});
+
+var contains = {contains: function(element){
+	return Slick.contains(this, element);
+}};
+
+if (!document.contains) Document.implement(contains);
+if (!document.createElement('div').contains) Element.implement(contains);
+
+
+
+// tree walking
+
+var injectCombinator = function(expression, combinator){
+	if (!expression) return combinator;
+
+	expression = Object.clone(Slick.parse(expression));
+
+	var expressions = expression.expressions;
+	for (var i = expressions.length; i--;)
+		expressions[i][0].combinator = combinator;
+
+	return expression;
+};
+
+Object.forEach({
+	getNext: '~',
+	getPrevious: '!~',
+	getParent: '!'
+}, function(combinator, method){
+	Element.implement(method, function(expression){
+		return this.getElement(injectCombinator(expression, combinator));
+	});
+});
+
+Object.forEach({
+	getAllNext: '~',
+	getAllPrevious: '!~',
+	getSiblings: '~~',
+	getChildren: '>',
+	getParents: '!'
+}, function(combinator, method){
+	Element.implement(method, function(expression){
+		return this.getElements(injectCombinator(expression, combinator));
+	});
+});
+
+Element.implement({
+
+	getFirst: function(expression){
+		return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
+	},
+
+	getLast: function(expression){
+		return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
+	},
+
+	getWindow: function(){
+		return this.ownerDocument.window;
+	},
+
+	getDocument: function(){
+		return this.ownerDocument;
+	},
+
+	getElementById: function(id){
+		return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
+	},
+
+	match: function(expression){
+		return !expression || Slick.match(this, expression);
+	}
+
+});
+
+
+
+if (window.$$ == null) Window.implement('$$', function(selector){
+	if (arguments.length == 1){
+		if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements);
+		else if (Type.isEnumerable(selector)) return new Elements(selector);
+	}
+	return new Elements(arguments);
+});
+
+// Inserters
+
+var inserters = {
+
+	before: function(context, element){
+		var parent = element.parentNode;
+		if (parent) parent.insertBefore(context, element);
+	},
+
+	after: function(context, element){
+		var parent = element.parentNode;
+		if (parent) parent.insertBefore(context, element.nextSibling);
+	},
+
+	bottom: function(context, element){
+		element.appendChild(context);
+	},
+
+	top: function(context, element){
+		element.insertBefore(context, element.firstChild);
+	}
+
+};
+
+inserters.inside = inserters.bottom;
+
+
+
+// getProperty / setProperty
+
+var propertyGetters = {}, propertySetters = {};
+
+// properties
+
+var properties = {};
+Array.forEach([
+	'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan',
+	'frameBorder', 'rowSpan', 'tabIndex', 'useMap'
+], function(property){
+	properties[property.toLowerCase()] = property;
+});
+
+properties.html = 'innerHTML';
+properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent';
+
+Object.forEach(properties, function(real, key){
+	propertySetters[key] = function(node, value){
+		node[real] = value;
+	};
+	propertyGetters[key] = function(node){
+		return node[real];
+	};
+});
+
+// Booleans
+
+var bools = [
+	'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked',
+	'disabled', 'readOnly', 'multiple', 'selected', 'noresize',
+	'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay',
+	'loop'
+];
+
+var booleans = {};
+Array.forEach(bools, function(bool){
+	var lower = bool.toLowerCase();
+	booleans[lower] = bool;
+	propertySetters[lower] = function(node, value){
+		node[bool] = !!value;
+	};
+	propertyGetters[lower] = function(node){
+		return !!node[bool];
+	};
+});
+
+// Special cases
+
+Object.append(propertySetters, {
+
+	'class': function(node, value){
+		('className' in node) ? node.className = (value || '') : node.setAttribute('class', value);
+	},
+
+	'for': function(node, value){
+		('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value);
+	},
+
+	'style': function(node, value){
+		(node.style) ? node.style.cssText = value : node.setAttribute('style', value);
+	},
+
+	'value': function(node, value){
+		node.value = (value != null) ? value : '';
+	}
+
+});
+
+propertyGetters['class'] = function(node){
+	return ('className' in node) ? node.className || null : node.getAttribute('class');
+};
+
+/* <webkit> */
+var el = document.createElement('button');
+// IE sets type as readonly and throws
+try { el.type = 'button'; } catch(e){}
+if (el.type != 'button') propertySetters.type = function(node, value){
+	node.setAttribute('type', value);
+};
+el = null;
+/* </webkit> */
+
+/*<IE>*/
+var input = document.createElement('input');
+input.value = 't';
+input.type = 'submit';
+if (input.value != 't') propertySetters.type = function(node, type){
+	var value = node.value;
+	node.type = type;
+	node.value = value;
+};
+input = null;
+/*</IE>*/
+
+/* getProperty, setProperty */
+
+/* <ltIE9> */
+var pollutesGetAttribute = (function(div){
+	div.random = 'attribute';
+	return (div.getAttribute('random') == 'attribute');
+})(document.createElement('div'));
+
+var hasCloneBug = (function(test){
+	test.innerHTML = '<object><param name="should_fix" value="the unknown"></object>';
+	return test.cloneNode(true).firstChild.childNodes.length != 1;
+})(document.createElement('div'));
+/* </ltIE9> */
+
+var hasClassList = !!document.createElement('div').classList;
+
+var classes = function(className){
+	var classNames = (className || '').clean().split(" "), uniques = {};
+	return classNames.filter(function(className){
+		if (className !== "" && !uniques[className]) return uniques[className] = className;
+	});
+};
+
+var addToClassList = function(name){
+	this.classList.add(name);
+};
+
+var removeFromClassList = function(name){
+	this.classList.remove(name);
+};
+
+Element.implement({
+
+	setProperty: function(name, value){
+		var setter = propertySetters[name.toLowerCase()];
+		if (setter){
+			setter(this, value);
+		} else {
+			/* <ltIE9> */
+			var attributeWhiteList;
+			if (pollutesGetAttribute) attributeWhiteList = this.retrieve('$attributeWhiteList', {});
+			/* </ltIE9> */
+
+			if (value == null){
+				this.removeAttribute(name);
+				/* <ltIE9> */
+				if (pollutesGetAttribute) delete attributeWhiteList[name];
+				/* </ltIE9> */
+			} else {
+				this.setAttribute(name, '' + value);
+				/* <ltIE9> */
+				if (pollutesGetAttribute) attributeWhiteList[name] = true;
+				/* </ltIE9> */
+			}
+		}
+		return this;
+	},
+
+	setProperties: function(attributes){
+		for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
+		return this;
+	},
+
+	getProperty: function(name){
+		var getter = propertyGetters[name.toLowerCase()];
+		if (getter) return getter(this);
+		/* <ltIE9> */
+		if (pollutesGetAttribute){
+			var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {});
+			if (!attr) return null;
+			if (attr.expando && !attributeWhiteList[name]){
+				var outer = this.outerHTML;
+				// segment by the opening tag and find mention of attribute name
+				if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null;
+				attributeWhiteList[name] = true;
+			}
+		}
+		/* </ltIE9> */
+		var result = Slick.getAttribute(this, name);
+		return (!result && !Slick.hasAttribute(this, name)) ? null : result;
+	},
+
+	getProperties: function(){
+		var args = Array.from(arguments);
+		return args.map(this.getProperty, this).associate(args);
+	},
+
+	removeProperty: function(name){
+		return this.setProperty(name, null);
+	},
+
+	removeProperties: function(){
+		Array.each(arguments, this.removeProperty, this);
+		return this;
+	},
+
+	set: function(prop, value){
+		var property = Element.Properties[prop];
+		(property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
+	}.overloadSetter(),
+
+	get: function(prop){
+		var property = Element.Properties[prop];
+		return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
+	}.overloadGetter(),
+
+	erase: function(prop){
+		var property = Element.Properties[prop];
+		(property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
+		return this;
+	},
+
+	hasClass: hasClassList ? function(className){
+		return this.classList.contains(className);
+	} : function(className){
+		return this.className.clean().contains(className, ' ');
+	},
+
+	addClass: hasClassList ? function(className){
+		classes(className).forEach(addToClassList, this);
+		return this;
+	} : function(className){
+		this.className = classes(className + ' ' + this.className).join(' ');
+		return this;
+	},
+
+	removeClass: hasClassList ? function(className){
+		classes(className).forEach(removeFromClassList, this);
+		return this;
+	} : function(className){
+		var classNames = classes(this.className);
+		classes(className).forEach(classNames.erase, classNames);
+		this.className = classNames.join(' ');
+		return this;
+	},
+
+	toggleClass: function(className, force){
+		if (force == null) force = !this.hasClass(className);
+		return (force) ? this.addClass(className) : this.removeClass(className);
+	},
+
+	adopt: function(){
+		var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length;
+		if (length > 1) parent = fragment = document.createDocumentFragment();
+
+		for (var i = 0; i < length; i++){
+			var element = document.id(elements[i], true);
+			if (element) parent.appendChild(element);
+		}
+
+		if (fragment) this.appendChild(fragment);
+
+		return this;
+	},
+
+	appendText: function(text, where){
+		return this.grab(this.getDocument().newTextNode(text), where);
+	},
+
+	grab: function(el, where){
+		inserters[where || 'bottom'](document.id(el, true), this);
+		return this;
+	},
+
+	inject: function(el, where){
+		inserters[where || 'bottom'](this, document.id(el, true));
+		return this;
+	},
+
+	replaces: function(el){
+		el = document.id(el, true);
+		el.parentNode.replaceChild(this, el);
+		return this;
+	},
+
+	wraps: function(el, where){
+		el = document.id(el, true);
+		return this.replaces(el).grab(el, where);
+	},
+
+	getSelected: function(){
+		this.selectedIndex; // Safari 3.2.1
+		return new Elements(Array.from(this.options).filter(function(option){
+			return option.selected;
+		}));
+	},
+
+	toQueryString: function(){
+		var queryString = [];
+		this.getElements('input, select, textarea').each(function(el){
+			var type = el.type;
+			if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return;
+
+			var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){
+				// IE
+				return document.id(opt).get('value');
+			}) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value');
+
+			Array.from(value).each(function(val){
+				if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val));
+			});
+		});
+		return queryString.join('&');
+	}
+
+});
+
+
+// appendHTML
+
+var appendInserters = {
+	before: 'beforeBegin',
+	after: 'afterEnd',
+	bottom: 'beforeEnd',
+	top: 'afterBegin',
+	inside: 'beforeEnd'
+};
+
+Element.implement('appendHTML', ('insertAdjacentHTML' in document.createElement('div')) ? function(html, where){
+	this.insertAdjacentHTML(appendInserters[where || 'bottom'], html);
+	return this;
+} : function(html, where){
+	var temp = new Element('div', {html: html}),
+		children = temp.childNodes,
+		fragment = temp.firstChild;
+
+	if (!fragment) return this;
+	if (children.length > 1){
+		fragment = document.createDocumentFragment();
+		for (var i = 0, l = children.length; i < l; i++){
+			fragment.appendChild(children[i]);
+		}
+	}
+
+	inserters[where || 'bottom'](fragment, this);
+	return this;
+});
+
+var collected = {}, storage = {};
+
+var get = function(uid){
+	return (storage[uid] || (storage[uid] = {}));
+};
+
+var clean = function(item){
+	var uid = item.uniqueNumber;
+	if (item.removeEvents) item.removeEvents();
+	if (item.clearAttributes) item.clearAttributes();
+	if (uid != null){
+		delete collected[uid];
+		delete storage[uid];
+	}
+	return item;
+};
+
+var formProps = {input: 'checked', option: 'selected', textarea: 'value'};
+
+Element.implement({
+
+	destroy: function(){
+		var children = clean(this).getElementsByTagName('*');
+		Array.each(children, clean);
+		Element.dispose(this);
+		return null;
+	},
+
+	empty: function(){
+		Array.from(this.childNodes).each(Element.dispose);
+		return this;
+	},
+
+	dispose: function(){
+		return (this.parentNode) ? this.parentNode.removeChild(this) : this;
+	},
+
+	clone: function(contents, keepid){
+		contents = contents !== false;
+		var clone = this.cloneNode(contents), ce = [clone], te = [this], i;
+
+		if (contents){
+			ce.append(Array.from(clone.getElementsByTagName('*')));
+			te.append(Array.from(this.getElementsByTagName('*')));
+		}
+
+		for (i = ce.length; i--;){
+			var node = ce[i], element = te[i];
+			if (!keepid) node.removeAttribute('id');
+			/*<ltIE9>*/
+			if (node.clearAttributes){
+				node.clearAttributes();
+				node.mergeAttributes(element);
+				node.removeAttribute('uniqueNumber');
+				if (node.options){
+					var no = node.options, eo = element.options;
+					for (var j = no.length; j--;) no[j].selected = eo[j].selected;
+				}
+			}
+			/*</ltIE9>*/
+			var prop = formProps[element.tagName.toLowerCase()];
+			if (prop && element[prop]) node[prop] = element[prop];
+		}
+
+		/*<ltIE9>*/
+		if (hasCloneBug){
+			var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object');
+			for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML;
+		}
+		/*</ltIE9>*/
+		return document.id(clone);
+	}
+
+});
+
+[Element, Window, Document].invoke('implement', {
+
+	addListener: function(type, fn){
+		if (window.attachEvent && !window.addEventListener){
+			collected[Slick.uidOf(this)] = this;
+		}
+		if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]);
+		else this.attachEvent('on' + type, fn);
+		return this;
+	},
+
+	removeListener: function(type, fn){
+		if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]);
+		else this.detachEvent('on' + type, fn);
+		return this;
+	},
+
+	retrieve: function(property, dflt){
+		var storage = get(Slick.uidOf(this)), prop = storage[property];
+		if (dflt != null && prop == null) prop = storage[property] = dflt;
+		return prop != null ? prop : null;
+	},
+
+	store: function(property, value){
+		var storage = get(Slick.uidOf(this));
+		storage[property] = value;
+		return this;
+	},
+
+	eliminate: function(property){
+		var storage = get(Slick.uidOf(this));
+		delete storage[property];
+		return this;
+	}
+
+});
+
+/*<ltIE9>*/
+if (window.attachEvent && !window.addEventListener){
+	var gc = function(){
+		Object.each(collected, clean);
+		if (window.CollectGarbage) CollectGarbage();
+		window.removeListener('unload', gc);
+	}
+	window.addListener('unload', gc);
+}
+/*</ltIE9>*/
+
+Element.Properties = {};
+
+
+
+Element.Properties.style = {
+
+	set: function(style){
+		this.style.cssText = style;
+	},
+
+	get: function(){
+		return this.style.cssText;
+	},
+
+	erase: function(){
+		this.style.cssText = '';
+	}
+
+};
+
+Element.Properties.tag = {
+
+	get: function(){
+		return this.tagName.toLowerCase();
+	}
+
+};
+
+Element.Properties.html = {
+
+	set: function(html){
+		if (html == null) html = '';
+		else if (typeOf(html) == 'array') html = html.join('');
+		this.innerHTML = html;
+	},
+
+	erase: function(){
+		this.innerHTML = '';
+	}
+
+};
+
+var supportsHTML5Elements = true, supportsTableInnerHTML = true, supportsTRInnerHTML = true;
+
+/*<ltIE9>*/
+// technique by jdbarlett - http://jdbartlett.com/innershiv/
+var div = document.createElement('div');
+div.innerHTML = '<nav></nav>';
+supportsHTML5Elements = (div.childNodes.length == 1);
+if (!supportsHTML5Elements){
+	var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '),
+		fragment = document.createDocumentFragment(), l = tags.length;
+	while (l--) fragment.createElement(tags[l]);
+}
+div = null;
+/*</ltIE9>*/
+
+/*<IE>*/
+supportsTableInnerHTML = Function.attempt(function(){
+	var table = document.createElement('table');
+	table.innerHTML = '<tr><td></td></tr>';
+	return true;
+});
+
+/*<ltFF4>*/
+var tr = document.createElement('tr'), html = '<td></td>';
+tr.innerHTML = html;
+supportsTRInnerHTML = (tr.innerHTML == html);
+tr = null;
+/*</ltFF4>*/
+
+if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){
+
+	Element.Properties.html.set = (function(set){
+
+		var translations = {
+			table: [1, '<table>', '</table>'],
+			select: [1, '<select>', '</select>'],
+			tbody: [2, '<table><tbody>', '</tbody></table>'],
+			tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
+		};
+
+		translations.thead = translations.tfoot = translations.tbody;
+
+		return function(html){
+			var wrap = translations[this.get('tag')];
+			if (!wrap && !supportsHTML5Elements) wrap = [0, '', ''];
+			if (!wrap) return set.call(this, html);
+
+			var level = wrap[0], wrapper = document.createElement('div'), target = wrapper;
+			if (!supportsHTML5Elements) fragment.appendChild(wrapper);
+			wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join('');
+			while (level--) target = target.firstChild;
+			this.empty().adopt(target.childNodes);
+			if (!supportsHTML5Elements) fragment.removeChild(wrapper);
+			wrapper = null;
+		};
+
+	})(Element.Properties.html.set);
+}
+/*</IE>*/
+
+/*<ltIE9>*/
+var testForm = document.createElement('form');
+testForm.innerHTML = '<select><option>s</option></select>';
+
+if (testForm.firstChild.value != 's') Element.Properties.value = {
+
+	set: function(value){
+		var tag = this.get('tag');
+		if (tag != 'select') return this.setProperty('value', value);
+		var options = this.getElements('option');
+		value = String(value);
+		for (var i = 0; i < options.length; i++){
+			var option = options[i],
+				attr = option.getAttributeNode('value'),
+				optionValue = (attr && attr.specified) ? option.value : option.get('text');
+			if (optionValue === value) return option.selected = true;
+		}
+	},
+
+	get: function(){
+		var option = this, tag = option.get('tag');
+
+		if (tag != 'select' && tag != 'option') return this.getProperty('value');
+
+		if (tag == 'select' && !(option = option.getSelected()[0])) return '';
+
+		var attr = option.getAttributeNode('value');
+		return (attr && attr.specified) ? option.value : option.get('text');
+	}
+
+};
+testForm = null;
+/*</ltIE9>*/
+
+/*<IE>*/
+if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = {
+	set: function(id){
+		this.id = this.getAttributeNode('id').value = id;
+	},
+	get: function(){
+		return this.id || null;
+	},
+	erase: function(){
+		this.id = this.getAttributeNode('id').value = '';
+	}
+};
+/*</IE>*/
+
+})();
+
+
+/*
+---
+
+name: Element.Style
+
+description: Contains methods for interacting with the styles of Elements in a fashionable way.
+
+license: MIT-style license.
+
+requires: Element
+
+provides: Element.Style
+
+...
+*/
+
+(function(){
+
+var html = document.html, el;
+
+//<ltIE9>
+// Check for oldIE, which does not remove styles when they're set to null
+el = document.createElement('div');
+el.style.color = 'red';
+el.style.color = null;
+var doesNotRemoveStyles = el.style.color == 'red';
+
+// check for oldIE, which returns border* shorthand styles in the wrong order (color-width-style instead of width-style-color)
+var border = '1px solid #123abc';
+el.style.border = border;
+var returnsBordersInWrongOrder = el.style.border != border;
+el = null;
+//</ltIE9>
+
+var hasGetComputedStyle = !!window.getComputedStyle;
+
+Element.Properties.styles = {set: function(styles){
+	this.setStyles(styles);
+}};
+
+var hasOpacity = (html.style.opacity != null),
+	hasFilter = (html.style.filter != null),
+	reAlpha = /alpha\(opacity=([\d.]+)\)/i;
+
+var setVisibility = function(element, opacity){
+	element.store('$opacity', opacity);
+	element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden';
+};
+
+//<ltIE9>
+var setFilter = function(element, regexp, value){
+	var style = element.style,
+		filter = style.filter || element.getComputedStyle('filter') || '';
+	style.filter = (regexp.test(filter) ? filter.replace(regexp, value) : filter + ' ' + value).trim();
+	if (!style.filter) style.removeAttribute('filter');
+};
+//</ltIE9>
+
+var setOpacity = (hasOpacity ? function(element, opacity){
+	element.style.opacity = opacity;
+} : (hasFilter ? function(element, opacity){
+	if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
+	if (opacity == null || opacity == 1){
+		setFilter(element, reAlpha, '');
+		if (opacity == 1 && getOpacity(element) != 1) setFilter(element, reAlpha, 'alpha(opacity=100)');
+	} else {
+		setFilter(element, reAlpha, 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')');
+	}
+} : setVisibility));
+
+var getOpacity = (hasOpacity ? function(element){
+	var opacity = element.style.opacity || element.getComputedStyle('opacity');
+	return (opacity == '') ? 1 : opacity.toFloat();
+} : (hasFilter ? function(element){
+	var filter = (element.style.filter || element.getComputedStyle('filter')),
+		opacity;
+	if (filter) opacity = filter.match(reAlpha);
+	return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
+} : function(element){
+	var opacity = element.retrieve('$opacity');
+	if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1);
+	return opacity;
+}));
+
+var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat',
+	namedPositions = {left: '0%', top: '0%', center: '50%', right: '100%', bottom: '100%'},
+	hasBackgroundPositionXY = (html.style.backgroundPositionX != null);
+
+//<ltIE9>
+var removeStyle = function(style, property){
+	if (property == 'backgroundPosition'){
+		style.removeAttribute(property + 'X');
+		property += 'Y';
+	}
+	style.removeAttribute(property);
+};
+//</ltIE9>
+
+Element.implement({
+
+	getComputedStyle: function(property){
+		if (!hasGetComputedStyle && this.currentStyle) return this.currentStyle[property.camelCase()];
+		var defaultView = Element.getDocument(this).defaultView,
+			computed = defaultView ? defaultView.getComputedStyle(this, null) : null;
+		return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : '';
+	},
+
+	setStyle: function(property, value){
+		if (property == 'opacity'){
+			if (value != null) value = parseFloat(value);
+			setOpacity(this, value);
+			return this;
+		}
+		property = (property == 'float' ? floatName : property).camelCase();
+		if (typeOf(value) != 'string'){
+			var map = (Element.Styles[property] || '@').split(' ');
+			value = Array.from(value).map(function(val, i){
+				if (!map[i]) return '';
+				return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
+			}).join(' ');
+		} else if (value == String(Number(value))){
+			value = Math.round(value);
+		}
+		this.style[property] = value;
+		//<ltIE9>
+		if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){
+			removeStyle(this.style, property);
+		}
+		//</ltIE9>
+		return this;
+	},
+
+	getStyle: function(property){
+		if (property == 'opacity') return getOpacity(this);
+		property = (property == 'float' ? floatName : property).camelCase();
+		var result = this.style[property];
+		if (!result || property == 'zIndex'){
+			if (Element.ShortStyles.hasOwnProperty(property)){
+				result = [];
+				for (var s in Element.ShortStyles[property]) result.push(this.getStyle(s));
+				return result.join(' ');
+			}
+			result = this.getComputedStyle(property);
+		}
+		if (hasBackgroundPositionXY && /^backgroundPosition[XY]?$/.test(property)){
+			return result.replace(/(top|right|bottom|left)/g, function(position){
+				return namedPositions[position];
+			}) || '0px';
+		}
+		if (!result && property == 'backgroundPosition') return '0px 0px';
+		if (result){
+			result = String(result);
+			var color = result.match(/rgba?\([\d\s,]+\)/);
+			if (color) result = result.replace(color[0], color[0].rgbToHex());
+		}
+		if (!hasGetComputedStyle && !this.style[property]){
+			if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){
+				var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
+				values.each(function(value){
+					size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
+				}, this);
+				return this['offset' + property.capitalize()] - size + 'px';
+			}
+			if ((/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){
+				return '0px';
+			}
+		}
+		//<ltIE9>
+		if (returnsBordersInWrongOrder && /^border(Top|Right|Bottom|Left)?$/.test(property) && /^#/.test(result)){
+			return result.replace(/^(.+)\s(.+)\s(.+)$/, '$2 $3 $1');
+		}
+		//</ltIE9>
+		return result;
+	},
+
+	setStyles: function(styles){
+		for (var style in styles) this.setStyle(style, styles[style]);
+		return this;
+	},
+
+	getStyles: function(){
+		var result = {};
+		Array.flatten(arguments).each(function(key){
+			result[key] = this.getStyle(key);
+		}, this);
+		return result;
+	}
+
+});
+
+Element.Styles = {
+	left: '@px', top: '@px', bottom: '@px', right: '@px',
+	width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
+	backgroundColor: 'rgb(@, @, @)', backgroundSize: '@px', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
+	fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
+	margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
+	borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
+	zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
+};
+
+
+
+
+
+Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
+
+['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
+	var Short = Element.ShortStyles;
+	var All = Element.Styles;
+	['margin', 'padding'].each(function(style){
+		var sd = style + direction;
+		Short[style][sd] = All[sd] = '@px';
+	});
+	var bd = 'border' + direction;
+	Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
+	var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
+	Short[bd] = {};
+	Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
+	Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
+	Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
+});
+
+if (hasBackgroundPositionXY) Element.ShortStyles.backgroundPosition = {backgroundPositionX: '@', backgroundPositionY: '@'};
+})();
+
+
+/*
+---
+
+name: Element.Event
+
+description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary.
+
+license: MIT-style license.
+
+requires: [Element, Event]
+
+provides: Element.Event
+
+...
+*/
+
+(function(){
+
+Element.Properties.events = {set: function(events){
+	this.addEvents(events);
+}};
+
+[Element, Window, Document].invoke('implement', {
+
+	addEvent: function(type, fn){
+		var events = this.retrieve('events', {});
+		if (!events[type]) events[type] = {keys: [], values: []};
+		if (events[type].keys.contains(fn)) return this;
+		events[type].keys.push(fn);
+		var realType = type,
+			custom = Element.Events[type],
+			condition = fn,
+			self = this;
+		if (custom){
+			if (custom.onAdd) custom.onAdd.call(this, fn, type);
+			if (custom.condition){
+				condition = function(event){
+					if (custom.condition.call(this, event, type)) return fn.call(this, event);
+					return true;
+				};
+			}
+			if (custom.base) realType = Function.from(custom.base).call(this, type);
+		}
+		var defn = function(){
+			return fn.call(self);
+		};
+		var nativeEvent = Element.NativeEvents[realType];
+		if (nativeEvent){
+			if (nativeEvent == 2){
+				defn = function(event){
+					event = new DOMEvent(event, self.getWindow());
+					if (condition.call(self, event) === false) event.stop();
+				};
+			}
+			this.addListener(realType, defn, arguments[2]);
+		}
+		events[type].values.push(defn);
+		return this;
+	},
+
+	removeEvent: function(type, fn){
+		var events = this.retrieve('events');
+		if (!events || !events[type]) return this;
+		var list = events[type];
+		var index = list.keys.indexOf(fn);
+		if (index == -1) return this;
+		var value = list.values[index];
+		delete list.keys[index];
+		delete list.values[index];
+		var custom = Element.Events[type];
+		if (custom){
+			if (custom.onRemove) custom.onRemove.call(this, fn, type);
+			if (custom.base) type = Function.from(custom.base).call(this, type);
+		}
+		return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
+	},
+
+	addEvents: function(events){
+		for (var event in events) this.addEvent(event, events[event]);
+		return this;
+	},
+
+	removeEvents: function(events){
+		var type;
+		if (typeOf(events) == 'object'){
+			for (type in events) this.removeEvent(type, events[type]);
+			return this;
+		}
+		var attached = this.retrieve('events');
+		if (!attached) return this;
+		if (!events){
+			for (type in attached) this.removeEvents(type);
+			this.eliminate('events');
+		} else if (attached[events]){
+			attached[events].keys.each(function(fn){
+				this.removeEvent(events, fn);
+			}, this);
+			delete attached[events];
+		}
+		return this;
+	},
+
+	fireEvent: function(type, args, delay){
+		var events = this.retrieve('events');
+		if (!events || !events[type]) return this;
+		args = Array.from(args);
+
+		events[type].keys.each(function(fn){
+			if (delay) fn.delay(delay, this, args);
+			else fn.apply(this, args);
+		}, this);
+		return this;
+	},
+
+	cloneEvents: function(from, type){
+		from = document.id(from);
+		var events = from.retrieve('events');
+		if (!events) return this;
+		if (!type){
+			for (var eventType in events) this.cloneEvents(from, eventType);
+		} else if (events[type]){
+			events[type].keys.each(function(fn){
+				this.addEvent(type, fn);
+			}, this);
+		}
+		return this;
+	}
+
+});
+
+Element.NativeEvents = {
+	click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
+	mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
+	mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
+	keydown: 2, keypress: 2, keyup: 2, //keyboard
+	orientationchange: 2, // mobile
+	touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
+	gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
+	focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements
+	load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
+	hashchange: 1, popstate: 2, // history
+	error: 1, abort: 1, scroll: 1 //misc
+};
+
+Element.Events = {
+	mousewheel: {
+		base: 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll'
+	}
+};
+
+var check = function(event){
+	var related = event.relatedTarget;
+	if (related == null) return true;
+	if (!related) return false;
+	return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
+};
+
+if ('onmouseenter' in document.documentElement){
+	Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2;
+	Element.MouseenterCheck = check;
+} else {
+	Element.Events.mouseenter = {
+		base: 'mouseover',
+		condition: check
+	};
+
+	Element.Events.mouseleave = {
+		base: 'mouseout',
+		condition: check
+	};
+}
+
+/*<ltIE9>*/
+if (!window.addEventListener){
+	Element.NativeEvents.propertychange = 2;
+	Element.Events.change = {
+		base: function(){
+			var type = this.type;
+			return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change';
+		},
+		condition: function(event){
+			return event.type != 'propertychange' || event.event.propertyName == 'checked';
+		}
+	};
+}
+/*</ltIE9>*/
+
+
+
+})();
+
+
+/*
+---
+
+name: Element.Delegation
+
+description: Extends the Element native object to include the delegate method for more efficient event management.
+
+license: MIT-style license.
+
+requires: [Element.Event]
+
+provides: [Element.Delegation]
+
+...
+*/
+
+(function(){
+
+var eventListenerSupport = !!window.addEventListener;
+
+Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2;
+
+var bubbleUp = function(self, match, fn, event, target){
+	while (target && target != self){
+		if (match(target, event)) return fn.call(target, event, target);
+		target = document.id(target.parentNode);
+	}
+};
+
+var map = {
+	mouseenter: {
+		base: 'mouseover',
+		condition: Element.MouseenterCheck
+	},
+	mouseleave: {
+		base: 'mouseout',
+		condition: Element.MouseenterCheck
+	},
+	focus: {
+		base: 'focus' + (eventListenerSupport ? '' : 'in'),
+		capture: true
+	},
+	blur: {
+		base: eventListenerSupport ? 'blur' : 'focusout',
+		capture: true
+	}
+};
+
+/*<ltIE9>*/
+var _key = '$delegation:';
+var formObserver = function(type){
+
+	return {
+
+		base: 'focusin',
+
+		remove: function(self, uid){
+			var list = self.retrieve(_key + type + 'listeners', {})[uid];
+			if (list && list.forms) for (var i = list.forms.length; i--;){
+				list.forms[i].removeEvent(type, list.fns[i]);
+			}
+		},
+
+		listen: function(self, match, fn, event, target, uid){
+			var form = (target.get('tag') == 'form') ? target : event.target.getParent('form');
+			if (!form) return;
+
+			var listeners = self.retrieve(_key + type + 'listeners', {}),
+				listener = listeners[uid] || {forms: [], fns: []},
+				forms = listener.forms, fns = listener.fns;
+
+			if (forms.indexOf(form) != -1) return;
+			forms.push(form);
+
+			var _fn = function(event){
+				bubbleUp(self, match, fn, event, target);
+			};
+			form.addEvent(type, _fn);
+			fns.push(_fn);
+
+			listeners[uid] = listener;
+			self.store(_key + type + 'listeners', listeners);
+		}
+	};
+};
+
+var inputObserver = function(type){
+	return {
+		base: 'focusin',
+		listen: function(self, match, fn, event, target){
+			var events = {blur: function(){
+				this.removeEvents(events);
+			}};
+			events[type] = function(event){
+				bubbleUp(self, match, fn, event, target);
+			};
+			event.target.addEvents(events);
+		}
+	};
+};
+
+if (!eventListenerSupport) Object.append(map, {
+	submit: formObserver('submit'),
+	reset: formObserver('reset'),
+	change: inputObserver('change'),
+	select: inputObserver('select')
+});
+/*</ltIE9>*/
+
+var proto = Element.prototype,
+	addEvent = proto.addEvent,
+	removeEvent = proto.removeEvent;
+
+var relay = function(old, method){
+	return function(type, fn, useCapture){
+		if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture);
+		var parsed = Slick.parse(type).expressions[0][0];
+		if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture);
+		var newType = parsed.tag;
+		parsed.pseudos.slice(1).each(function(pseudo){
+			newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : '');
+		});
+		old.call(this, type, fn);
+		return method.call(this, newType, parsed.pseudos[0].value, fn);
+	};
+};
+
+var delegation = {
+
+	addEvent: function(type, match, fn){
+		var storage = this.retrieve('$delegates', {}), stored = storage[type];
+		if (stored) for (var _uid in stored){
+			if (stored[_uid].fn == fn && stored[_uid].match == match) return this;
+		}
+
+		var _type = type, _match = match, _fn = fn, _map = map[type] || {};
+		type = _map.base || _type;
+
+		match = function(target){
+			return Slick.match(target, _match);
+		};
+
+		var elementEvent = Element.Events[_type];
+		if (_map.condition || elementEvent && elementEvent.condition){
+			var __match = match, condition = _map.condition || elementEvent.condition;
+			match = function(target, event){
+				return __match(target, event) && condition.call(target, event, type);
+			};
+		}
+
+		var self = this, uid = String.uniqueID();
+		var delegator = _map.listen ? function(event, target){
+			if (!target && event && event.target) target = event.target;
+			if (target) _map.listen(self, match, fn, event, target, uid);
+		} : function(event, target){
+			if (!target && event && event.target) target = event.target;
+			if (target) bubbleUp(self, match, fn, event, target);
+		};
+
+		if (!stored) stored = {};
+		stored[uid] = {
+			match: _match,
+			fn: _fn,
+			delegator: delegator
+		};
+		storage[_type] = stored;
+		return addEvent.call(this, type, delegator, _map.capture);
+	},
+
+	removeEvent: function(type, match, fn, _uid){
+		var storage = this.retrieve('$delegates', {}), stored = storage[type];
+		if (!stored) return this;
+
+		if (_uid){
+			var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {};
+			type = _map.base || _type;
+			if (_map.remove) _map.remove(this, _uid);
+			delete stored[_uid];
+			storage[_type] = stored;
+			return removeEvent.call(this, type, delegator, _map.capture);
+		}
+
+		var __uid, s;
+		if (fn) for (__uid in stored){
+			s = stored[__uid];
+			if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid);
+		} else for (__uid in stored){
+			s = stored[__uid];
+			if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid);
+		}
+		return this;
+	}
+
+};
+
+[Element, Window, Document].invoke('implement', {
+	addEvent: relay(addEvent, delegation.addEvent),
+	removeEvent: relay(removeEvent, delegation.removeEvent)
+});
+
+})();
+
+
+/*
+---
+
+name: Element.Dimensions
+
+description: Contains methods to work with size, scroll, or positioning of Elements and the window object.
+
+license: MIT-style license.
+
+credits:
+  - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
+  - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
+
+requires: [Element, Element.Style]
+
+provides: [Element.Dimensions]
+
+...
+*/
+
+(function(){
+
+var element = document.createElement('div'),
+	child = document.createElement('div');
+element.style.height = '0';
+element.appendChild(child);
+var brokenOffsetParent = (child.offsetParent === element);
+element = child = null;
+
+var isOffset = function(el){
+	return styleString(el, 'position') != 'static' || isBody(el);
+};
+
+var isOffsetStatic = function(el){
+	return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName);
+};
+
+Element.implement({
+
+	scrollTo: function(x, y){
+		if (isBody(this)){
+			this.getWindow().scrollTo(x, y);
+		} else {
+			this.scrollLeft = x;
+			this.scrollTop = y;
+		}
+		return this;
+	},
+
+	getSize: function(){
+		if (isBody(this)) return this.getWindow().getSize();
+		return {x: this.offsetWidth, y: this.offsetHeight};
+	},
+
+	getScrollSize: function(){
+		if (isBody(this)) return this.getWindow().getScrollSize();
+		return {x: this.scrollWidth, y: this.scrollHeight};
+	},
+
+	getScroll: function(){
+		if (isBody(this)) return this.getWindow().getScroll();
+		return {x: this.scrollLeft, y: this.scrollTop};
+	},
+
+	getScrolls: function(){
+		var element = this.parentNode, position = {x: 0, y: 0};
+		while (element && !isBody(element)){
+			position.x += element.scrollLeft;
+			position.y += element.scrollTop;
+			element = element.parentNode;
+		}
+		return position;
+	},
+
+	getOffsetParent: brokenOffsetParent ? function(){
+		var element = this;
+		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
+
+		var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset;
+		while ((element = element.parentNode)){
+			if (isOffsetCheck(element)) return element;
+		}
+		return null;
+	} : function(){
+		var element = this;
+		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
+
+		try {
+			return element.offsetParent;
+		} catch(e) {}
+		return null;
+	},
+
+	getOffsets: function(){
+		var hasGetBoundingClientRect = this.getBoundingClientRect;
+
+		if (hasGetBoundingClientRect){
+			var bound = this.getBoundingClientRect(),
+				html = document.id(this.getDocument().documentElement),
+				htmlScroll = html.getScroll(),
+				elemScrolls = this.getScrolls(),
+				isFixed = (styleString(this, 'position') == 'fixed');
+
+			return {
+				x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft,
+				y: bound.top.toInt()  + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop
+			};
+		}
+
+		var element = this, position = {x: 0, y: 0};
+		if (isBody(this)) return position;
+
+		while (element && !isBody(element)){
+			position.x += element.offsetLeft;
+			position.y += element.offsetTop;
+
+			element = element.offsetParent;
+		}
+
+		return position;
+	},
+
+	getPosition: function(relative){
+		var offset = this.getOffsets(),
+			scroll = this.getScrolls();
+		var position = {
+			x: offset.x - scroll.x,
+			y: offset.y - scroll.y
+		};
+
+		if (relative && (relative = document.id(relative))){
+			var relativePosition = relative.getPosition();
+			return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)};
+		}
+		return position;
+	},
+
+	getCoordinates: function(element){
+		if (isBody(this)) return this.getWindow().getCoordinates();
+		var position = this.getPosition(element),
+			size = this.getSize();
+		var obj = {
+			left: position.x,
+			top: position.y,
+			width: size.x,
+			height: size.y
+		};
+		obj.right = obj.left + obj.width;
+		obj.bottom = obj.top + obj.height;
+		return obj;
+	},
+
+	computePosition: function(obj){
+		return {
+			left: obj.x - styleNumber(this, 'margin-left'),
+			top: obj.y - styleNumber(this, 'margin-top')
+		};
+	},
+
+	setPosition: function(obj){
+		return this.setStyles(this.computePosition(obj));
+	}
+
+});
+
+
+[Document, Window].invoke('implement', {
+
+	getSize: function(){
+		var doc = getCompatElement(this);
+		return {x: doc.clientWidth, y: doc.clientHeight};
+	},
+
+	getScroll: function(){
+		var win = this.getWindow(), doc = getCompatElement(this);
+		return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
+	},
+
+	getScrollSize: function(){
+		var doc = getCompatElement(this),
+			min = this.getSize(),
+			body = this.getDocument().body;
+
+		return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)};
+	},
+
+	getPosition: function(){
+		return {x: 0, y: 0};
+	},
+
+	getCoordinates: function(){
+		var size = this.getSize();
+		return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
+	}
+
+});
+
+// private methods
+
+var styleString = Element.getComputedStyle;
+
+function styleNumber(element, style){
+	return styleString(element, style).toInt() || 0;
+}
+
+function borderBox(element){
+	return styleString(element, '-moz-box-sizing') == 'border-box';
+}
+
+function topBorder(element){
+	return styleNumber(element, 'border-top-width');
+}
+
+function leftBorder(element){
+	return styleNumber(element, 'border-left-width');
+}
+
+function isBody(element){
+	return (/^(?:body|html)$/i).test(element.tagName);
+}
+
+function getCompatElement(element){
+	var doc = element.getDocument();
+	return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
+}
+
+})();
+
+//aliases
+Element.alias({position: 'setPosition'}); //compatability
+
+[Window, Document, Element].invoke('implement', {
+
+	getHeight: function(){
+		return this.getSize().y;
+	},
+
+	getWidth: function(){
+		return this.getSize().x;
+	},
+
+	getScrollTop: function(){
+		return this.getScroll().y;
+	},
+
+	getScrollLeft: function(){
+		return this.getScroll().x;
+	},
+
+	getScrollHeight: function(){
+		return this.getScrollSize().y;
+	},
+
+	getScrollWidth: function(){
+		return this.getScrollSize().x;
+	},
+
+	getTop: function(){
+		return this.getPosition().y;
+	},
+
+	getLeft: function(){
+		return this.getPosition().x;
+	}
+
+});
+
+
+/*
+---
+
+name: Fx
+
+description: Contains the basic animation logic to be extended by all other Fx Classes.
+
+license: MIT-style license.
+
+requires: [Chain, Events, Options]
+
+provides: Fx
+
+...
+*/
+
+(function(){
+
+var Fx = this.Fx = new Class({
+
+	Implements: [Chain, Events, Options],
+
+	options: {
+		/*
+		onStart: nil,
+		onCancel: nil,
+		onComplete: nil,
+		*/
+		fps: 60,
+		unit: false,
+		duration: 500,
+		frames: null,
+		frameSkip: true,
+		link: 'ignore'
+	},
+
+	initialize: function(options){
+		this.subject = this.subject || this;
+		this.setOptions(options);
+	},
+
+	getTransition: function(){
+		return function(p){
+			return -(Math.cos(Math.PI * p) - 1) / 2;
+		};
+	},
+
+	step: function(now){
+		if (this.options.frameSkip){
+			var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval;
+			this.time = now;
+			this.frame += frames;
+		} else {
+			this.frame++;
+		}
+
+		if (this.frame < this.frames){
+			var delta = this.transition(this.frame / this.frames);
+			this.set(this.compute(this.from, this.to, delta));
+		} else {
+			this.frame = this.frames;
+			this.set(this.compute(this.from, this.to, 1));
+			this.stop();
+		}
+	},
+
+	set: function(now){
+		return now;
+	},
+
+	compute: function(from, to, delta){
+		return Fx.compute(from, to, delta);
+	},
+
+	check: function(){
+		if (!this.isRunning()) return true;
+		switch (this.options.link){
+			case 'cancel': this.cancel(); return true;
+			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
+		}
+		return false;
+	},
+
+	start: function(from, to){
+		if (!this.check(from, to)) return this;
+		this.from = from;
+		this.to = to;
+		this.frame = (this.options.frameSkip) ? 0 : -1;
+		this.time = null;
+		this.transition = this.getTransition();
+		var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration;
+		this.duration = Fx.Durations[duration] || duration.toInt();
+		this.frameInterval = 1000 / fps;
+		this.frames = frames || Math.round(this.duration / this.frameInterval);
+		this.fireEvent('start', this.subject);
+		pushInstance.call(this, fps);
+		return this;
+	},
+
+	stop: function(){
+		if (this.isRunning()){
+			this.time = null;
+			pullInstance.call(this, this.options.fps);
+			if (this.frames == this.frame){
+				this.fireEvent('complete', this.subject);
+				if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
+			} else {
+				this.fireEvent('stop', this.subject);
+			}
+		}
+		return this;
+	},
+
+	cancel: function(){
+		if (this.isRunning()){
+			this.time = null;
+			pullInstance.call(this, this.options.fps);
+			this.frame = this.frames;
+			this.fireEvent('cancel', this.subject).clearChain();
+		}
+		return this;
+	},
+
+	pause: function(){
+		if (this.isRunning()){
+			this.time = null;
+			pullInstance.call(this, this.options.fps);
+		}
+		return this;
+	},
+
+	resume: function(){
+		if (this.isPaused()) pushInstance.call(this, this.options.fps);
+		return this;
+	},
+
+	isRunning: function(){
+		var list = instances[this.options.fps];
+		return list && list.contains(this);
+	},
+
+	isPaused: function(){
+		return (this.frame < this.frames) && !this.isRunning();
+	}
+
+});
+
+Fx.compute = function(from, to, delta){
+	return (to - from) * delta + from;
+};
+
+Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
+
+// global timers
+
+var instances = {}, timers = {};
+
+var loop = function(){
+	var now = Date.now();
+	for (var i = this.length; i--;){
+		var instance = this[i];
+		if (instance) instance.step(now);
+	}
+};
+
+var pushInstance = function(fps){
+	var list = instances[fps] || (instances[fps] = []);
+	list.push(this);
+	if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
+};
+
+var pullInstance = function(fps){
+	var list = instances[fps];
+	if (list){
+		list.erase(this);
+		if (!list.length && timers[fps]){
+			delete instances[fps];
+			timers[fps] = clearInterval(timers[fps]);
+		}
+	}
+};
+
+})();
+
+
+/*
+---
+
+name: Fx.CSS
+
+description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
+
+license: MIT-style license.
+
+requires: [Fx, Element.Style]
+
+provides: Fx.CSS
+
+...
+*/
+
+Fx.CSS = new Class({
+
+	Extends: Fx,
+
+	//prepares the base from/to object
+
+	prepare: function(element, property, values){
+		values = Array.from(values);
+		var from = values[0], to = values[1];
+		if (to == null){
+			to = from;
+			from = element.getStyle(property);
+			var unit = this.options.unit;
+			// adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299
+			if (unit && from && typeof from == 'string' && from.slice(-unit.length) != unit && parseFloat(from) != 0){
+				element.setStyle(property, to + unit);
+				var value = element.getComputedStyle(property);
+				// IE and Opera support pixelLeft or pixelWidth
+				if (!(/px$/.test(value))){
+					value = element.style[('pixel-' + property).camelCase()];
+					if (value == null){
+						// adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+						var left = element.style.left;
+						element.style.left = to + unit;
+						value = element.style.pixelLeft;
+						element.style.left = left;
+					}
+				}
+				from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0);
+				element.setStyle(property, from + unit);
+			}
+		}
+		return {from: this.parse(from), to: this.parse(to)};
+	},
+
+	//parses a value into an array
+
+	parse: function(value){
+		value = Function.from(value)();
+		value = (typeof value == 'string') ? value.split(' ') : Array.from(value);
+		return value.map(function(val){
+			val = String(val);
+			var found = false;
+			Object.each(Fx.CSS.Parsers, function(parser, key){
+				if (found) return;
+				var parsed = parser.parse(val);
+				if (parsed || parsed === 0) found = {value: parsed, parser: parser};
+			});
+			found = found || {value: val, parser: Fx.CSS.Parsers.String};
+			return found;
+		});
+	},
+
+	//computes by a from and to prepared objects, using their parsers.
+
+	compute: function(from, to, delta){
+		var computed = [];
+		(Math.min(from.length, to.length)).times(function(i){
+			computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
+		});
+		computed.$family = Function.from('fx:css:value');
+		return computed;
+	},
+
+	//serves the value as settable
+
+	serve: function(value, unit){
+		if (typeOf(value) != 'fx:css:value') value = this.parse(value);
+		var returned = [];
+		value.each(function(bit){
+			returned = returned.concat(bit.parser.serve(bit.value, unit));
+		});
+		return returned;
+	},
+
+	//renders the change to an element
+
+	render: function(element, property, value, unit){
+		element.setStyle(property, this.serve(value, unit));
+	},
+
+	//searches inside the page css to find the values for a selector
+
+	search: function(selector){
+		if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
+		var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$');
+
+		var searchStyles = function(rules){
+			Array.each(rules, function(rule, i){
+				if (rule.media){
+					searchStyles(rule.rules || rule.cssRules);
+					return;
+				}
+				if (!rule.style) return;
+				var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
+					return m.toLowerCase();
+				}) : null;
+				if (!selectorText || !selectorTest.test(selectorText)) return;
+				Object.each(Element.Styles, function(value, style){
+					if (!rule.style[style] || Element.ShortStyles[style]) return;
+					value = String(rule.style[style]);
+					to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value;
+				});
+			});
+		};
+
+		Array.each(document.styleSheets, function(sheet, j){
+			var href = sheet.href;
+			if (href && href.indexOf('://') > -1 && href.indexOf(document.domain) == -1) return;
+			var rules = sheet.rules || sheet.cssRules;
+			searchStyles(rules);
+		});
+		return Fx.CSS.Cache[selector] = to;
+	}
+
+});
+
+Fx.CSS.Cache = {};
+
+Fx.CSS.Parsers = {
+
+	Color: {
+		parse: function(value){
+			if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
+			return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
+		},
+		compute: function(from, to, delta){
+			return from.map(function(value, i){
+				return Math.round(Fx.compute(from[i], to[i], delta));
+			});
+		},
+		serve: function(value){
+			return value.map(Number);
+		}
+	},
+
+	Number: {
+		parse: parseFloat,
+		compute: Fx.compute,
+		serve: function(value, unit){
+			return (unit) ? value + unit : value;
+		}
+	},
+
+	String: {
+		parse: Function.from(false),
+		compute: function(zero, one){
+			return one;
+		},
+		serve: function(zero){
+			return zero;
+		}
+	}
+
+};
+
+
+
+
+/*
+---
+
+name: Fx.Tween
+
+description: Formerly Fx.Style, effect to transition any CSS property for an element.
+
+license: MIT-style license.
+
+requires: Fx.CSS
+
+provides: [Fx.Tween, Element.fade, Element.highlight]
+
+...
+*/
+
+Fx.Tween = new Class({
+
+	Extends: Fx.CSS,
+
+	initialize: function(element, options){
+		this.element = this.subject = document.id(element);
+		this.parent(options);
+	},
+
+	set: function(property, now){
+		if (arguments.length == 1){
+			now = property;
+			property = this.property || this.options.property;
+		}
+		this.render(this.element, property, now, this.options.unit);
+		return this;
+	},
+
+	start: function(property, from, to){
+		if (!this.check(property, from, to)) return this;
+		var args = Array.flatten(arguments);
+		this.property = this.options.property || args.shift();
+		var parsed = this.prepare(this.element, this.property, args);
+		return this.parent(parsed.from, parsed.to);
+	}
+
+});
+
+Element.Properties.tween = {
+
+	set: function(options){
+		this.get('tween').cancel().setOptions(options);
+		return this;
+	},
+
+	get: function(){
+		var tween = this.retrieve('tween');
+		if (!tween){
+			tween = new Fx.Tween(this, {link: 'cancel'});
+			this.store('tween', tween);
+		}
+		return tween;
+	}
+
+};
+
+Element.implement({
+
+	tween: function(property, from, to){
+		this.get('tween').start(property, from, to);
+		return this;
+	},
+
+	fade: function(how){
+		var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle;
+		if (args[1] == null) args[1] = 'toggle';
+		switch (args[1]){
+			case 'in': method = 'start'; args[1] = 1; break;
+			case 'out': method = 'start'; args[1] = 0; break;
+			case 'show': method = 'set'; args[1] = 1; break;
+			case 'hide': method = 'set'; args[1] = 0; break;
+			case 'toggle':
+				var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1);
+				method = 'start';
+				args[1] = flag ? 0 : 1;
+				this.store('fade:flag', !flag);
+				toggle = true;
+			break;
+			default: method = 'start';
+		}
+		if (!toggle) this.eliminate('fade:flag');
+		fade[method].apply(fade, args);
+		var to = args[args.length - 1];
+		if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible');
+		else fade.chain(function(){
+			this.element.setStyle('visibility', 'hidden');
+			this.callChain();
+		});
+		return this;
+	},
+
+	highlight: function(start, end){
+		if (!end){
+			end = this.retrieve('highlight:original', this.getStyle('background-color'));
+			end = (end == 'transparent') ? '#fff' : end;
+		}
+		var tween = this.get('tween');
+		tween.start('background-color', start || '#ffff88', end).chain(function(){
+			this.setStyle('background-color', this.retrieve('highlight:original'));
+			tween.callChain();
+		}.bind(this));
+		return this;
+	}
+
+});
+
+
+/*
+---
+
+name: Fx.Morph
+
+description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.
+
+license: MIT-style license.
+
+requires: Fx.CSS
+
+provides: Fx.Morph
+
+...
+*/
+
+Fx.Morph = new Class({
+
+	Extends: Fx.CSS,
+
+	initialize: function(element, options){
+		this.element = this.subject = document.id(element);
+		this.parent(options);
+	},
+
+	set: function(now){
+		if (typeof now == 'string') now = this.search(now);
+		for (var p in now) this.render(this.element, p, now[p], this.options.unit);
+		return this;
+	},
+
+	compute: function(from, to, delta){
+		var now = {};
+		for (var p in from) now[p] = this.parent(from[p], to[p], delta);
+		return now;
+	},
+
+	start: function(properties){
+		if (!this.check(properties)) return this;
+		if (typeof properties == 'string') properties = this.search(properties);
+		var from = {}, to = {};
+		for (var p in properties){
+			var parsed = this.prepare(this.element, p, properties[p]);
+			from[p] = parsed.from;
+			to[p] = parsed.to;
+		}
+		return this.parent(from, to);
+	}
+
+});
+
+Element.Properties.morph = {
+
+	set: function(options){
+		this.get('morph').cancel().setOptions(options);
+		return this;
+	},
+
+	get: function(){
+		var morph = this.retrieve('morph');
+		if (!morph){
+			morph = new Fx.Morph(this, {link: 'cancel'});
+			this.store('morph', morph);
+		}
+		return morph;
+	}
+
+};
+
+Element.implement({
+
+	morph: function(props){
+		this.get('morph').start(props);
+		return this;
+	}
+
+});
+
+
+/*
+---
+
+name: Fx.Transitions
+
+description: Contains a set of advanced transitions to be used with any of the Fx Classes.
+
+license: MIT-style license.
+
+credits:
+  - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
+
+requires: Fx
+
+provides: Fx.Transitions
+
+...
+*/
+
+Fx.implement({
+
+	getTransition: function(){
+		var trans = this.options.transition || Fx.Transitions.Sine.easeInOut;
+		if (typeof trans == 'string'){
+			var data = trans.split(':');
+			trans = Fx.Transitions;
+			trans = trans[data[0]] || trans[data[0].capitalize()];
+			if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')];
+		}
+		return trans;
+	}
+
+});
+
+Fx.Transition = function(transition, params){
+	params = Array.from(params);
+	var easeIn = function(pos){
+		return transition(pos, params);
+	};
+	return Object.append(easeIn, {
+		easeIn: easeIn,
+		easeOut: function(pos){
+			return 1 - transition(1 - pos, params);
+		},
+		easeInOut: function(pos){
+			return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2;
+		}
+	});
+};
+
+Fx.Transitions = {
+
+	linear: function(zero){
+		return zero;
+	}
+
+};
+
+
+
+Fx.Transitions.extend = function(transitions){
+	for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
+};
+
+Fx.Transitions.extend({
+
+	Pow: function(p, x){
+		return Math.pow(p, x && x[0] || 6);
+	},
+
+	Expo: function(p){
+		return Math.pow(2, 8 * (p - 1));
+	},
+
+	Circ: function(p){
+		return 1 - Math.sin(Math.acos(p));
+	},
+
+	Sine: function(p){
+		return 1 - Math.cos(p * Math.PI / 2);
+	},
+
+	Back: function(p, x){
+		x = x && x[0] || 1.618;
+		return Math.pow(p, 2) * ((x + 1) * p - x);
+	},
+
+	Bounce: function(p){
+		var value;
+		for (var a = 0, b = 1; 1; a += b, b /= 2){
+			if (p >= (7 - 4 * a) / 11){
+				value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
+				break;
+			}
+		}
+		return value;
+	},
+
+	Elastic: function(p, x){
+		return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3);
+	}
+
+});
+
+['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
+	Fx.Transitions[transition] = new Fx.Transition(function(p){
+		return Math.pow(p, i + 2);
+	});
+});
+
+
+/*
+---
+
+name: Request
+
+description: Powerful all purpose Request Class. Uses XMLHTTPRequest.
+
+license: MIT-style license.
+
+requires: [Object, Element, Chain, Events, Options, Browser]
+
+provides: Request
+
+...
+*/
+
+(function(){
+
+var empty = function(){},
+	progressSupport = ('onprogress' in new Browser.Request);
+
+var Request = this.Request = new Class({
+
+	Implements: [Chain, Events, Options],
+
+	options: {/*
+		onRequest: function(){},
+		onLoadstart: function(event, xhr){},
+		onProgress: function(event, xhr){},
+		onComplete: function(){},
+		onCancel: function(){},
+		onSuccess: function(responseText, responseXML){},
+		onFailure: function(xhr){},
+		onException: function(headerName, value){},
+		onTimeout: function(){},
+		user: '',
+		password: '',*/
+		url: '',
+		data: '',
+		headers: {
+			'X-Requested-With': 'XMLHttpRequest',
+			'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+		},
+		async: true,
+		format: false,
+		method: 'post',
+		link: 'ignore',
+		isSuccess: null,
+		emulation: true,
+		urlEncoded: true,
+		encoding: 'utf-8',
+		evalScripts: false,
+		evalResponse: false,
+		timeout: 0,
+		noCache: false
+	},
+
+	initialize: function(options){
+		this.xhr = new Browser.Request();
+		this.setOptions(options);
+		this.headers = this.options.headers;
+	},
+
+	onStateChange: function(){
+		var xhr = this.xhr;
+		if (xhr.readyState != 4 || !this.running) return;
+		this.running = false;
+		this.status = 0;
+		Function.attempt(function(){
+			var status = xhr.status;
+			this.status = (status == 1223) ? 204 : status;
+		}.bind(this));
+		xhr.onreadystatechange = empty;
+		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
+		clearTimeout(this.timer);
+
+		this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML};
+		if (this.options.isSuccess.call(this, this.status))
+			this.success(this.response.text, this.response.xml);
+		else
+			this.failure();
+	},
+
+	isSuccess: function(){
+		var status = this.status;
+		return (status >= 200 && status < 300);
+	},
+
+	isRunning: function(){
+		return !!this.running;
+	},
+
+	processScripts: function(text){
+		if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text);
+		return text.stripScripts(this.options.evalScripts);
+	},
+
+	success: function(text, xml){
+		this.onSuccess(this.processScripts(text), xml);
+	},
+
+	onSuccess: function(){
+		this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
+	},
+
+	failure: function(){
+		this.onFailure();
+	},
+
+	onFailure: function(){
+		this.fireEvent('complete').fireEvent('failure', this.xhr);
+	},
+
+	loadstart: function(event){
+		this.fireEvent('loadstart', [event, this.xhr]);
+	},
+
+	progress: function(event){
+		this.fireEvent('progress', [event, this.xhr]);
+	},
+
+	timeout: function(){
+		this.fireEvent('timeout', this.xhr);
+	},
+
+	setHeader: function(name, value){
+		this.headers[name] = value;
+		return this;
+	},
+
+	getHeader: function(name){
+		return Function.attempt(function(){
+			return this.xhr.getResponseHeader(name);
+		}.bind(this));
+	},
+
+	check: function(){
+		if (!this.running) return true;
+		switch (this.options.link){
+			case 'cancel': this.cancel(); return true;
+			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
+		}
+		return false;
+	},
+
+	send: function(options){
+		if (!this.check(options)) return this;
+
+		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
+		this.running = true;
+
+		var type = typeOf(options);
+		if (type == 'string' || type == 'element') options = {data: options};
+
+		var old = this.options;
+		options = Object.append({data: old.data, url: old.url, method: old.method}, options);
+		var data = options.data, url = String(options.url), method = options.method.toLowerCase();
+
+		switch (typeOf(data)){
+			case 'element': data = document.id(data).toQueryString(); break;
+			case 'object': case 'hash': data = Object.toQueryString(data);
+		}
+
+		if (this.options.format){
+			var format = 'format=' + this.options.format;
+			data = (data) ? format + '&' + data : format;
+		}
+
+		if (this.options.emulation && !['get', 'post'].contains(method)){
+			var _method = '_method=' + method;
+			data = (data) ? _method + '&' + data : _method;
+			method = 'post';
+		}
+
+		if (this.options.urlEncoded && ['post', 'put'].contains(method)){
+			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
+			this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding;
+		}
+
+		if (!url) url = document.location.pathname;
+
+		var trimPosition = url.lastIndexOf('/');
+		if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition);
+
+		if (this.options.noCache)
+			url += (url.indexOf('?') > -1 ? '&' : '?') + String.uniqueID();
+
+		if (data && (method == 'get' || method == 'delete')){
+			url += (url.indexOf('?') > -1 ? '&' : '?') + data;
+			data = null;
+		}
+
+		var xhr = this.xhr;
+		if (progressSupport){
+			xhr.onloadstart = this.loadstart.bind(this);
+			xhr.onprogress = this.progress.bind(this);
+		}
+
+		xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password);
+		if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true;
+
+		xhr.onreadystatechange = this.onStateChange.bind(this);
+
+		Object.each(this.headers, function(value, key){
+			try {
+				xhr.setRequestHeader(key, value);
+			} catch (e){
+				this.fireEvent('exception', [key, value]);
+			}
+		}, this);
+
+		this.fireEvent('request');
+		xhr.send(data);
+		if (!this.options.async) this.onStateChange();
+		else if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this);
+		return this;
+	},
+
+	cancel: function(){
+		if (!this.running) return this;
+		this.running = false;
+		var xhr = this.xhr;
+		xhr.abort();
+		clearTimeout(this.timer);
+		xhr.onreadystatechange = empty;
+		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
+		this.xhr = new Browser.Request();
+		this.fireEvent('cancel');
+		return this;
+	}
+
+});
+
+var methods = {};
+['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
+	methods[method] = function(data){
+		var object = {
+			method: method
+		};
+		if (data != null) object.data = data;
+		return this.send(object);
+	};
+});
+
+Request.implement(methods);
+
+Element.Properties.send = {
+
+	set: function(options){
+		var send = this.get('send').cancel();
+		send.setOptions(options);
+		return this;
+	},
+
+	get: function(){
+		var send = this.retrieve('send');
+		if (!send){
+			send = new Request({
+				data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
+			});
+			this.store('send', send);
+		}
+		return send;
+	}
+
+};
+
+Element.implement({
+
+	send: function(url){
+		var sender = this.get('send');
+		sender.send({data: this, url: url || sender.options.url});
+		return this;
+	}
+
+});
+
+})();
+
+
+/*
+---
+
+name: Request.HTML
+
+description: Extends the basic Request Class with additional methods for interacting with HTML responses.
+
+license: MIT-style license.
+
+requires: [Element, Request]
+
+provides: Request.HTML
+
+...
+*/
+
+Request.HTML = new Class({
+
+	Extends: Request,
+
+	options: {
+		update: false,
+		append: false,
+		evalScripts: true,
+		filter: false,
+		headers: {
+			Accept: 'text/html, application/xml, text/xml, */*'
+		}
+	},
+
+	success: function(text){
+		var options = this.options, response = this.response;
+
+		response.html = text.stripScripts(function(script){
+			response.javascript = script;
+		});
+
+		var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
+		if (match) response.html = match[1];
+		var temp = new Element('div').set('html', response.html);
+
+		response.tree = temp.childNodes;
+		response.elements = temp.getElements(options.filter || '*');
+
+		if (options.filter) response.tree = response.elements;
+		if (options.update){
+			var update = document.id(options.update).empty();
+			if (options.filter) update.adopt(response.elements);
+			else update.set('html', response.html);
+		} else if (options.append){
+			var append = document.id(options.append);
+			if (options.filter) response.elements.reverse().inject(append);
+			else append.adopt(temp.getChildren());
+		}
+		if (options.evalScripts) Browser.exec(response.javascript);
+
+		this.onSuccess(response.tree, response.elements, response.html, response.javascript);
+	}
+
+});
+
+Element.Properties.load = {
+
+	set: function(options){
+		var load = this.get('load').cancel();
+		load.setOptions(options);
+		return this;
+	},
+
+	get: function(){
+		var load = this.retrieve('load');
+		if (!load){
+			load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'});
+			this.store('load', load);
+		}
+		return load;
+	}
+
+};
+
+Element.implement({
+
+	load: function(){
+		this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString}));
+		return this;
+	}
+
+});
+
+
+/*
+---
+
+name: JSON
+
+description: JSON encoder and decoder.
+
+license: MIT-style license.
+
+SeeAlso: <http://www.json.org/>
+
+requires: [Array, String, Number, Function]
+
+provides: JSON
+
+...
+*/
+
+if (typeof JSON == 'undefined') this.JSON = {};
+
+
+
+(function(){
+
+var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'};
+
+var escape = function(chr){
+	return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4);
+};
+
+JSON.validate = function(string){
+	string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+					replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+					replace(/(?:^|:|,)(?:\s*\[)+/g, '');
+
+	return (/^[\],:{}\s]*$/).test(string);
+};
+
+JSON.encode = JSON.stringify ? function(obj){
+	return JSON.stringify(obj);
+} : function(obj){
+	if (obj && obj.toJSON) obj = obj.toJSON();
+
+	switch (typeOf(obj)){
+		case 'string':
+			return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';
+		case 'array':
+			return '[' + obj.map(JSON.encode).clean() + ']';
+		case 'object': case 'hash':
+			var string = [];
+			Object.each(obj, function(value, key){
+				var json = JSON.encode(value);
+				if (json) string.push(JSON.encode(key) + ':' + json);
+			});
+			return '{' + string + '}';
+		case 'number': case 'boolean': return '' + obj;
+		case 'null': return 'null';
+	}
+
+	return null;
+};
+
+JSON.secure = true;
+
+
+JSON.decode = function(string, secure){
+	if (!string || typeOf(string) != 'string') return null;
+    
+	if (secure == null) secure = JSON.secure; 
+	if (secure){
+		if (JSON.parse) return JSON.parse(string);
+		if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.');
+	}
+
+	return eval('(' + string + ')');
+};
+
+})();
+
+
+/*
+---
+
+name: Request.JSON
+
+description: Extends the basic Request Class with additional methods for sending and receiving JSON data.
+
+license: MIT-style license.
+
+requires: [Request, JSON]
+
+provides: Request.JSON
+
+...
+*/
+
+Request.JSON = new Class({
+
+	Extends: Request,
+
+	options: {
+		/*onError: function(text, error){},*/
+		secure: true
+	},
+
+	initialize: function(options){
+		this.parent(options);
+		Object.append(this.headers, {
+			'Accept': 'application/json',
+			'X-Request': 'JSON'
+		});
+	},
+
+	success: function(text){
+		var json;
+		try {
+			json = this.response.json = JSON.decode(text, this.options.secure);
+		} catch (error){
+			this.fireEvent('error', [text, error]);
+			return;
+		}
+		if (json == null) this.onFailure();
+		else this.onSuccess(json, text);
+	}
+
+});
+
+
+/*
+---
+
+name: Cookie
+
+description: Class for creating, reading, and deleting browser Cookies.
+
+license: MIT-style license.
+
+credits:
+  - Based on the functions by Peter-Paul Koch (http://quirksmode.org).
+
+requires: [Options, Browser]
+
+provides: Cookie
+
+...
+*/
+
+var Cookie = new Class({
+
+	Implements: Options,
+
+	options: {
+		path: '/',
+		domain: false,
+		duration: false,
+		secure: false,
+		document: document,
+		encode: true
+	},
+
+	initialize: function(key, options){
+		this.key = key;
+		this.setOptions(options);
+	},
+
+	write: function(value){
+		if (this.options.encode) value = encodeURIComponent(value);
+		if (this.options.domain) value += '; domain=' + this.options.domain;
+		if (this.options.path) value += '; path=' + this.options.path;
+		if (this.options.duration){
+			var date = new Date();
+			date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
+			value += '; expires=' + date.toGMTString();
+		}
+		if (this.options.secure) value += '; secure';
+		this.options.document.cookie = this.key + '=' + value;
+		return this;
+	},
+
+	read: function(){
+		var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
+		return (value) ? decodeURIComponent(value[1]) : null;
+	},
+
+	dispose: function(){
+		new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write('');
+		return this;
+	}
+
+});
+
+Cookie.write = function(key, value, options){
+	return new Cookie(key, options).write(value);
+};
+
+Cookie.read = function(key){
+	return new Cookie(key).read();
+};
+
+Cookie.dispose = function(key, options){
+	return new Cookie(key, options).dispose();
+};
+
+
+/*
+---
+
+name: DOMReady
+
+description: Contains the custom event domready.
+
+license: MIT-style license.
+
+requires: [Browser, Element, Element.Event]
+
+provides: [DOMReady, DomReady]
+
+...
+*/
+
+(function(window, document){
+
+var ready,
+	loaded,
+	checks = [],
+	shouldPoll,
+	timer,
+	testElement = document.createElement('div');
+
+var domready = function(){
+	clearTimeout(timer);
+	if (ready) return;
+	Browser.loaded = ready = true;
+	document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check);
+
+	document.fireEvent('domready');
+	window.fireEvent('domready');
+};
+
+var check = function(){
+	for (var i = checks.length; i--;) if (checks[i]()){
+		domready();
+		return true;
+	}
+	return false;
+};
+
+var poll = function(){
+	clearTimeout(timer);
+	if (!check()) timer = setTimeout(poll, 10);
+};
+
+document.addListener('DOMContentLoaded', domready);
+
+/*<ltIE8>*/
+// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/
+// testElement.doScroll() throws when the DOM is not ready, only in the top window
+var doScrollWorks = function(){
+	try {
+		testElement.doScroll();
+		return true;
+	} catch (e){}
+	return false;
+};
+// If doScroll works already, it can't be used to determine domready
+//   e.g. in an iframe
+if (testElement.doScroll && !doScrollWorks()){
+	checks.push(doScrollWorks);
+	shouldPoll = true;
+}
+/*</ltIE8>*/
+
+if (document.readyState) checks.push(function(){
+	var state = document.readyState;
+	return (state == 'loaded' || state == 'complete');
+});
+
+if ('onreadystatechange' in document) document.addListener('readystatechange', check);
+else shouldPoll = true;
+
+if (shouldPoll) poll();
+
+Element.Events.domready = {
+	onAdd: function(fn){
+		if (ready) fn.call(this);
+	}
+};
+
+// Make sure that domready fires before load
+Element.Events.load = {
+	base: 'load',
+	onAdd: function(fn){
+		if (loaded && this == window) fn.call(this);
+	},
+	condition: function(){
+		if (this == window){
+			domready();
+			delete Element.Events.load;
+		}
+		return true;
+	}
+};
+
+// This is based on the custom load event
+window.addEvent('load', function(){
+	loaded = true;
+});
+
+})(window, document);
+
diff --git a/trace-viewer/third_party/css-element-queries/test/mootools-more-yui-compressed.min.js b/trace-viewer/third_party/css-element-queries/test/mootools-more-yui-compressed.min.js
new file mode 100644
index 0000000..6bf24b8
--- /dev/null
+++ b/trace-viewer/third_party/css-element-queries/test/mootools-more-yui-compressed.min.js
@@ -0,0 +1 @@
+MooTools.More={version:"1.5.0",build:"73db5e24e6e9c5c87b3a27aebef2248053f7db37"};(function(){Events.Pseudos=function(a,j,i){var k="_monitorEvents:";var l=function(e){return{store:e.store?function(g,f){e.store(k+g,f)}:function(g,f){(e._monitorEvents||(e._monitorEvents={}))[g]=f},retrieve:e.retrieve?function(g,f){return e.retrieve(k+g,f)}:function(g,f){if(!e._monitorEvents){return f}return e._monitorEvents[g]||f}}};var b=function(f){if(f.indexOf(":")==-1||!a){return null}var g=Slick.parse(f).expressions[0][0],q=g.pseudos,h=q.length,r=[];while(h--){var s=q[h].key,e=a[s];if(e!=null){r.push({event:g.tag,value:q[h].value,pseudo:s,original:f,listener:e})}}return r.length?r:null};return{addEvent:function(t,g,w){var s=b(t);if(!s){return j.call(this,t,g,w)}var v=l(this),e=v.retrieve(t,[]),x=s[0].event,u=Array.slice(arguments,2),h=g,f=this;s.each(function(o){var n=o.listener,m=h;if(n==false){x+=":"+o.pseudo+"("+o.value+")"}else{h=function(){n.call(f,o,m,arguments,h)}}});e.include({type:x,event:g,monitor:h});v.store(t,e);if(t!=x){j.apply(this,[t,g].concat(u))}return j.apply(this,[x,h].concat(u))},removeEvent:function(e,f){var g=b(e);if(!g){return i.call(this,e,f)}var p=l(this),h=p.retrieve(e);if(!h){return this}var o=Array.slice(arguments,2);i.apply(this,[e,f].concat(o));h.each(function(n,m){if(!f||n.event==f){i.apply(this,[n.type,n.monitor].concat(o))}delete h[m]},this);p.store(e,h);return this}}};var c={once:function(b,a,g,h){a.apply(this,g);this.removeEvent(b.event,h).removeEvent(b.original,a)},throttle:function(b,a,f){if(!a._throttled){a.apply(this,f);a._throttled=setTimeout(function(){a._throttled=false},b.value||250)}},pause:function(b,a,f){clearTimeout(a._pause);a._pause=a.delay(b.value||250,this,f)}};Events.definePseudo=function(b,a){c[b]=a;return this};Events.lookupPseudo=function(a){return c[a]};var d=Events.prototype;Events.implement(Events.Pseudos(c,d.addEvent,d.removeEvent));["Request","Fx"].each(function(a){if(this[a]){this[a].implement(Events.prototype)}})})();Class.refactor=function(c,d){Object.each(d,function(a,b){var f=c.prototype[b];f=(f&&f.$origin)||f||function(){};c.implement(b,(typeof a=="function")?function(){var h=this.previous;this.previous=f;var e=a.apply(this,arguments);this.previous=h;return e}:a)});return c};Class.Mutators.Binds=function(b){if(!this.prototype.initialize){this.implement("initialize",function(){})}return Array.from(b).concat(this.prototype.Binds||[])};Class.Mutators.initialize=function(b){return function(){Array.from(this.Binds).each(function(a){var d=this[a];if(d){this[a]=d.bind(this)}},this);return b.apply(this,arguments)}};Class.Occlude=new Class({occlude:function(f,d){d=document.id(d||this.element);var e=d.retrieve(f||this.property);if(e&&!this.occluded){return(this.occluded=e)}this.occluded=false;d.store(f||this.property,this);return this.occluded}});(function(){var b={wait:function(a){return this.chain(function(){this.callChain.delay(a==null?500:a,this);return this}.bind(this))}};Chain.implement(b);if(this.Fx){Fx.implement(b)}if(this.Element&&Element.implement&&this.Fx){Element.implement({chains:function(a){Array.from(a||["tween","morph","reveal"]).each(function(d){d=this.get(d);if(!d){return}d.setOptions({link:"chain"})},this);return this},pauseFx:function(d,a){this.chains(a).get(a||"tween").wait(d);return this}})}})();(function(b){Array.implement({min:function(){return Math.min.apply(null,this)},max:function(){return Math.max.apply(null,this)},average:function(){return this.length?this.sum()/this.length:0},sum:function(){var a=0,d=this.length;if(d){while(d--){if(this[d]!=null){a+=parseFloat(this[d])}}}return a},unique:function(){return[].combine(this)},shuffle:function(){for(var f=this.length;f&&--f;){var a=this[f],e=Math.floor(Math.random()*(f+1));this[f]=this[e];this[e]=a}return this},reduce:function(g,f){for(var h=0,a=this.length;h<a;h++){if(h in this){f=f===b?this[h]:g.call(null,f,this[h],h,this)}}return f},reduceRight:function(f,e){var a=this.length;while(a--){if(a in this){e=e===b?this[a]:f.call(null,e,this[a],a,this)}}return e},pluck:function(a){return this.map(function(d){return d[a]})}})})();(function(){var c=function(a){return a!=null};var d=Object.prototype.hasOwnProperty;Object.extend({getFromPath:function(b,a){if(typeof a=="string"){a=a.split(".")}for(var g=0,h=a.length;g<h;g++){if(d.call(b,a[g])){b=b[a[g]]}else{return null}}return b},cleanValues:function(f,a){a=a||c;for(var b in f){if(!a(f[b])){delete f[b]}}return f},erase:function(b,a){if(d.call(b,a)){delete b[a]}return b},run:function(b){var f=Array.slice(arguments,1);for(var a in b){if(b[a].apply){b[a].apply(b,f)}}return b}})})();(function(){var f=null,g={},i={};var j=function(a){if(instanceOf(a,h.Set)){return a}else{return g[a]}};var h=this.Locale={define:function(e,a,c,b){var d;if(instanceOf(e,h.Set)){d=e.name;if(d){g[d]=e}}else{d=e;if(!g[d]){g[d]=new h.Set(d)}e=g[d]}if(a){e.define(a,c,b)}if(!f){f=e}return e},use:function(a){a=j(a);if(a){f=a;this.fireEvent("change",a)}return this},getCurrent:function(){return f},get:function(a,b){return(f)?f.get(a,b):""},inherit:function(c,b,a){c=j(c);if(c){c.inherit(b,a)}return this},list:function(){return Object.keys(g)}};Object.append(h,new Events);h.Set=new Class({sets:{},inherits:{locales:[],sets:{}},initialize:function(a){this.name=a||""},define:function(a,c,b){var d=this.sets[a];if(!d){d={}}if(c){if(typeOf(c)=="object"){d=Object.merge(d,c)}else{d[c]=b}}this.sets[a]=d;return this},get:function(a,t,b){var c=Object.getFromPath(this.sets,a);if(c!=null){var l=typeOf(c);if(l=="function"){c=c.apply(null,Array.from(t))}else{if(l=="object"){c=Object.clone(c)}}return c}var u=a.indexOf("."),d=u<0?a:a.substr(0,u),s=(this.inherits.sets[d]||[]).combine(this.inherits.locales).include("en-US");if(!b){b=[]}for(var v=0,w=s.length;v<w;v++){if(b.contains(s[v])){continue}b.include(s[v]);var e=g[s[v]];if(!e){continue}c=e.get(a,t,b);if(c!=null){return c}}return""},inherit:function(b,a){b=Array.from(b);if(a&&!this.inherits.sets[a]){this.inherits.sets[a]=[]}var c=b.length;while(c--){(a?this.inherits.sets[a]:this.inherits.locales).unshift(b[c])}return this}})})();Locale.define("en-US","Date",{months:["January","February","March","April","May","June","July","August","September","October","November","December"],months_abbr:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],days_abbr:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dateOrder:["month","date","year"],shortDate:"%m/%d/%Y",shortTime:"%I:%M%p",AM:"AM",PM:"PM",firstDayOfWeek:0,ordinal:function(b){return(b>3&&b<21)?"th":["th","st","nd","rd","th"][Math.min(b%10,4)]},lessThanMinuteAgo:"less than a minute ago",minuteAgo:"about a minute ago",minutesAgo:"{delta} minutes ago",hourAgo:"about an hour ago",hoursAgo:"about {delta} hours ago",dayAgo:"1 day ago",daysAgo:"{delta} days ago",weekAgo:"1 week ago",weeksAgo:"{delta} weeks ago",monthAgo:"1 month ago",monthsAgo:"{delta} months ago",yearAgo:"1 year ago",yearsAgo:"{delta} years ago",lessThanMinuteUntil:"less than a minute from now",minuteUntil:"about a minute from now",minutesUntil:"{delta} minutes from now",hourUntil:"about an hour from now",hoursUntil:"about {delta} hours from now",dayUntil:"1 day from now",daysUntil:"{delta} days from now",weekUntil:"1 week from now",weeksUntil:"{delta} weeks from now",monthUntil:"1 month from now",monthsUntil:"{delta} months from now",yearUntil:"1 year from now",yearsUntil:"{delta} years from now"});(function(){var J=this.Date;var E=J.Methods={ms:"Milliseconds",year:"FullYear",min:"Minutes",mo:"Month",sec:"Seconds",hr:"Hours"};["Date","Day","FullYear","Hours","Milliseconds","Minutes","Month","Seconds","Time","TimezoneOffset","Week","Timezone","GMTOffset","DayOfYear","LastMonth","LastDayOfMonth","UTCDate","UTCDay","UTCFullYear","AMPM","Ordinal","UTCHours","UTCMilliseconds","UTCMinutes","UTCMonth","UTCSeconds","UTCMilliseconds"].each(function(a){J.Methods[a.toLowerCase()]=a});var u=function(a,b,c){if(b==1){return a}return a<Math.pow(10,b-1)?(c||"0")+u(a,b-1,c):a};J.implement({set:function(a,c){a=a.toLowerCase();var b=E[a]&&"set"+E[a];if(b&&this[b]){this[b](c)}return this}.overloadSetter(),get:function(a){a=a.toLowerCase();var b=E[a]&&"get"+E[a];if(b&&this[b]){return this[b]()}return null}.overloadGetter(),clone:function(){return new J(this.get("time"))},increment:function(c,a){c=c||"day";a=a!=null?a:1;switch(c){case"year":return this.increment("month",a*12);case"month":var b=this.get("date");this.set("date",1).set("mo",this.get("mo")+a);return this.set("date",b.min(this.get("lastdayofmonth")));case"week":return this.increment("day",a*7);case"day":return this.set("date",this.get("date")+a)}if(!J.units[c]){throw new Error(c+" is not a supported interval")}return this.set("time",this.get("time")+a*J.units[c]())},decrement:function(b,a){return this.increment(b,-1*(a!=null?a:1))},isLeapYear:function(){return J.isLeapYear(this.get("year"))},clearTime:function(){return this.set({hr:0,min:0,sec:0,ms:0})},diff:function(a,b){if(typeOf(a)=="string"){a=J.parse(a)}return((a-this)/J.units[b||"day"](3,3)).round()},getLastDayOfMonth:function(){return J.daysInMonth(this.get("mo"),this.get("year"))},getDayOfYear:function(){return(J.UTC(this.get("year"),this.get("mo"),this.get("date")+1)-J.UTC(this.get("year"),0,1))/J.units.day()},setDay:function(b,c){if(c==null){c=J.getMsg("firstDayOfWeek");if(c===""){c=1}}b=(7+J.parseDay(b,true)-c)%7;var a=(7+this.get("day")-c)%7;return this.increment("day",b-a)},getWeek:function(c){if(c==null){c=J.getMsg("firstDayOfWeek");if(c===""){c=1}}var a=this,d=(7+a.get("day")-c)%7,e=0,b;if(c==1){var g=a.get("month"),f=a.get("date")-d;if(g==11&&f>28){return 1}if(g==0&&f<-2){a=new J(a).decrement("day",d);d=0}b=new J(a.get("year"),0,1).get("day")||7;if(b>4){e=-7}}else{b=new J(a.get("year"),0,1).get("day")}e+=a.get("dayofyear");e+=6-d;e+=(7+b-c)%7;return(e/7)},getOrdinal:function(a){return J.getMsg("ordinal",a||this.get("date"))},getTimezone:function(){return this.toString().replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/,"$1").replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/,"$1$2$3")},getGMTOffset:function(){var a=this.get("timezoneOffset");return((a>0)?"-":"+")+u((a.abs()/60).floor(),2)+u(a%60,2)},setAMPM:function(b){b=b.toUpperCase();var a=this.get("hr");if(a>11&&b=="AM"){return this.decrement("hour",12)}else{if(a<12&&b=="PM"){return this.increment("hour",12)}}return this},getAMPM:function(){return(this.get("hr")<12)?"AM":"PM"},parse:function(a){this.set("time",J.parse(a));return this},isValid:function(a){if(!a){a=this}return typeOf(a)=="date"&&!isNaN(a.valueOf())},format:function(b){if(!this.isValid()){return"invalid date"}if(!b){b="%x %X"}if(typeof b=="string"){b=D[b.toLowerCase()]||b}if(typeof b=="function"){return b(this)}var a=this;return b.replace(/%([a-z%])/gi,function(c,d){switch(d){case"a":return J.getMsg("days_abbr")[a.get("day")];case"A":return J.getMsg("days")[a.get("day")];case"b":return J.getMsg("months_abbr")[a.get("month")];case"B":return J.getMsg("months")[a.get("month")];case"c":return a.format("%a %b %d %H:%M:%S %Y");case"d":return u(a.get("date"),2);case"e":return u(a.get("date"),2," ");case"H":return u(a.get("hr"),2);case"I":return u((a.get("hr")%12)||12,2);case"j":return u(a.get("dayofyear"),3);case"k":return u(a.get("hr"),2," ");case"l":return u((a.get("hr")%12)||12,2," ");case"L":return u(a.get("ms"),3);case"m":return u((a.get("mo")+1),2);case"M":return u(a.get("min"),2);case"o":return a.get("ordinal");case"p":return J.getMsg(a.get("ampm"));case"s":return Math.round(a/1000);case"S":return u(a.get("seconds"),2);case"T":return a.format("%H:%M:%S");case"U":return u(a.get("week"),2);case"w":return a.get("day");case"x":return a.format(J.getMsg("shortDate"));case"X":return a.format(J.getMsg("shortTime"));case"y":return a.get("year").toString().substr(2);case"Y":return a.get("year");case"z":return a.get("GMTOffset");case"Z":return a.get("Timezone")}return d})},toISOString:function(){return this.format("iso8601")}}).alias({toJSON:"toISOString",compare:"diff",strftime:"format"});var z=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],C=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];var D={db:"%Y-%m-%d %H:%M:%S",compact:"%Y%m%dT%H%M%S","short":"%d %b %H:%M","long":"%B %d, %Y %H:%M",rfc822:function(a){return z[a.get("day")]+a.format(", %d ")+C[a.get("month")]+a.format(" %Y %H:%M:%S %Z")},rfc2822:function(a){return z[a.get("day")]+a.format(", %d ")+C[a.get("month")]+a.format(" %Y %H:%M:%S %z")},iso8601:function(a){return(a.getUTCFullYear()+"-"+u(a.getUTCMonth()+1,2)+"-"+u(a.getUTCDate(),2)+"T"+u(a.getUTCHours(),2)+":"+u(a.getUTCMinutes(),2)+":"+u(a.getUTCSeconds(),2)+"."+u(a.getUTCMilliseconds(),3)+"Z")}};var H=[],w=J.parse;var s=function(c,a,d){var e=-1,b=J.getMsg(c+"s");switch(typeOf(a)){case"object":e=b[a.get(c)];break;case"number":e=b[a];if(!e){throw new Error("Invalid "+c+" index: "+a)}break;case"string":var f=b.filter(function(g){return this.test(g)},new RegExp("^"+a,"i"));if(!f.length){throw new Error("Invalid "+c+" string")}if(f.length>1){throw new Error("Ambiguous "+c)}e=f[0]}return(d)?b.indexOf(e):e};var B=1900,v=70;J.extend({getMsg:function(a,b){return Locale.get("Date."+a,b)},units:{ms:Function.from(1),second:Function.from(1000),minute:Function.from(60000),hour:Function.from(3600000),day:Function.from(86400000),week:Function.from(608400000),month:function(b,c){var a=new J;return J.daysInMonth(b!=null?b:a.get("mo"),c!=null?c:a.get("year"))*86400000},year:function(a){a=a||new J().get("year");return J.isLeapYear(a)?31622400000:31536000000}},daysInMonth:function(a,b){return[31,J.isLeapYear(b)?29:28,31,30,31,30,31,31,30,31,30,31][a]},isLeapYear:function(a){return((a%4===0)&&(a%100!==0))||(a%400===0)},parse:function(a){var b=typeOf(a);if(b=="number"){return new J(a)}if(b!="string"){return a}a=a.clean();if(!a.length){return null}var c;H.some(function(d){var e=d.re.exec(a);return(e)?(c=d.handler(e)):false});if(!(c&&c.isValid())){c=new J(w(a));if(!(c&&c.isValid())){c=new J(a.toInt())}}return c},parseDay:function(b,a){return s("day",b,a)},parseMonth:function(a,b){return s("month",a,b)},parseUTC:function(b){var c=new J(b);var a=J.UTC(c.get("year"),c.get("mo"),c.get("date"),c.get("hr"),c.get("min"),c.get("sec"),c.get("ms"));return new J(a)},orderIndex:function(a){return J.getMsg("dateOrder").indexOf(a)+1},defineFormat:function(b,a){D[b]=a;return this},defineParser:function(a){H.push((a.re&&a.handler)?a:y(a));return this},defineParsers:function(){Array.flatten(arguments).each(J.defineParser);return this},define2DigitYearStart:function(a){v=a%100;B=a-v;return this}}).extend({defineFormats:J.defineFormat.overloadSetter()});var G=function(a){return new RegExp("(?:"+J.getMsg(a).map(function(b){return b.substr(0,3)}).join("|")+")[a-z]*")};var x=function(a){switch(a){case"T":return"%H:%M:%S";case"x":return((J.orderIndex("month")==1)?"%m[-./]%d":"%d[-./]%m")+"([-./]%y)?";case"X":return"%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%z?"}return null};var A={d:/[0-2]?[0-9]|3[01]/,H:/[01]?[0-9]|2[0-3]/,I:/0?[1-9]|1[0-2]/,M:/[0-5]?\d/,s:/\d+/,o:/[a-z]*/,p:/[ap]\.?m\.?/,y:/\d{2}|\d{4}/,Y:/\d{4}/,z:/Z|[+-]\d{2}(?::?\d{2})?/};A.m=A.I;A.S=A.M;var F;var I=function(a){F=a;A.a=A.A=G("days");A.b=A.B=G("months");H.each(function(b,c){if(b.format){H[c]=y(b.format)}})};var y=function(a){if(!F){return{format:a}}var c=[];var b=(a.source||a).replace(/%([a-z])/gi,function(d,e){return x(e)||d}).replace(/\((?!\?)/g,"(?:").replace(/ (?!\?|\*)/g,",? ").replace(/%([a-z%])/gi,function(e,f){var d=A[f];if(!d){return f}c.push(f);return"("+d.source+")"}).replace(/\[a-z\]/gi,"[a-z\\u00c0-\\uffff;&]");return{format:a,re:new RegExp("^"+b+"$","i"),handler:function(g){g=g.slice(1).associate(c);var f=new J().clearTime(),d=g.y||g.Y;if(d!=null){t.call(f,"y",d)}if("d" in g){t.call(f,"d",1)}if("m" in g||g.b||g.B){t.call(f,"m",1)}for(var e in g){t.call(f,e,g[e])}return f}}};var t=function(c,b){if(!b){return this}switch(c){case"a":case"A":return this.set("day",J.parseDay(b,true));case"b":case"B":return this.set("mo",J.parseMonth(b,true));case"d":return this.set("date",b);case"H":case"I":return this.set("hr",b);case"m":return this.set("mo",b-1);case"M":return this.set("min",b);case"p":return this.set("ampm",b.replace(/\./g,""));case"S":return this.set("sec",b);case"s":return this.set("ms",("0."+b)*1000);case"w":return this.set("day",b);case"Y":return this.set("year",b);case"y":b=+b;if(b<100){b+=B+(b<v?100:0)}return this.set("year",b);case"z":if(b=="Z"){b="+00"}var a=b.match(/([+-])(\d{2}):?(\d{2})?/);a=(a[1]+"1")*(a[2]*60+(+a[3]||0))+this.getTimezoneOffset();return this.set("time",this-a*60000)}return this};J.defineParsers("%Y([-./]%m([-./]%d((T| )%X)?)?)?","%Y%m%d(T%H(%M%S?)?)?","%x( %X)?","%d%o( %b( %Y)?)?( %X)?","%b( %d%o)?( %Y)?( %X)?","%Y %b( %d%o( %X)?)?","%o %b %d %X %z %Y","%T","%H:%M( ?%p)?");Locale.addEvent("change",function(a){if(Locale.get("Date")){I(a)}}).fireEvent("change",Locale.getCurrent())})();Date.implement({timeDiffInWords:function(b){return Date.distanceOfTimeInWords(this,b||new Date)},timeDiff:function(m,p){if(m==null){m=new Date}var k=((m-this)/1000).floor().abs();var n=[],r=[60,60,24,365,0],o=["s","m","h","d","y"],l,q;for(var j=0;j<r.length;j++){if(j&&!k){break}l=k;if((q=r[j])){l=(k%q);k=(k/q).floor()}n.unshift(l+(o[j]||""))}return n.join(p||":")}}).extend({distanceOfTimeInWords:function(c,d){return Date.getTimePhrase(((d-c)/1000).toInt())},getTimePhrase:function(i){var k=(i<0)?"Until":"Ago";if(i<0){i*=-1}var g={minute:60,hour:60,day:24,week:7,month:52/12,year:12,eon:Infinity};var j="lessThanMinute";for(var l in g){var h=g[l];if(i<1.5*h){if(i>0.75*h){j=l}break}i/=h;j=l+"s"}i=i.round();return Date.getMsg(j+k,i).substitute({delta:i})}}).defineParsers({re:/^(?:tod|tom|yes)/i,handler:function(d){var c=new Date().clearTime();switch(d[0]){case"tom":return c.increment();case"yes":return c.decrement();default:return c}}},{re:/^(next|last) ([a-z]+)$/i,handler:function(i){var h=new Date().clearTime();var d=h.getDay();var j=Date.parseDay(i[2],true);var g=j-d;if(j<=d){g+=7}if(i[1]=="last"){g-=7}return h.set("date",h.getDate()+g)}}).alias("timeAgoInWords","timeDiffInWords");Locale.define("en-US","Number",{decimal:".",group:",",currency:{prefix:"$ "}});Number.implement({format:function(i){var t=this;i=i?Object.clone(i):{};var F=function(a){if(i[a]!=null){return i[a]}return Locale.get("Number."+a)};var A=t<0,y=F("decimal"),w=F("precision"),s=F("group"),D=F("decimals");if(A){var B=F("negative")||{};if(B.prefix==null&&B.suffix==null){B.prefix="-"}["prefix","suffix"].each(function(a){if(B[a]){i[a]=F(a)+B[a]}});t=-t}var v=F("prefix"),r=F("suffix");if(D!==""&&D>=0&&D<=20){t=t.toFixed(D)}if(w>=1&&w<=21){t=(+t).toPrecision(w)}t+="";var u;if(F("scientific")===false&&t.indexOf("e")>-1){var x=t.split("e"),E=+x[1];t=x[0].replace(".","");if(E<0){E=-E-1;u=x[0].indexOf(".");if(u>-1){E-=u-1}while(E--){t="0"+t}t="0."+t}else{u=x[0].lastIndexOf(".");if(u>-1){E-=x[0].length-u-1}while(E--){t+="0"}}}if(y!="."){t=t.replace(".",y)}if(s){u=t.lastIndexOf(y);u=(u>-1)?u:t.length;var C=t.substring(u),z=u;while(z--){if((u-z-1)%3==0&&z!=(u-1)){C=s+C}C=t.charAt(z)+C}t=C}if(v){t=v+t}if(r){t+=r}return t},formatCurrency:function(c){var d=Locale.get("Number.currency")||{};if(d.scientific==null){d.scientific=false}d.decimals=c!=null?c:(d.decimals==null?2:d.decimals);return this.format(d)},formatPercentage:function(c){var d=Locale.get("Number.percentage")||{};if(d.suffix==null){d.suffix="%"}d.decimals=c!=null?c:(d.decimals==null?2:d.decimals);return this.format(d)}});(function(){var j={a:/[àáâãäåăą]/g,A:/[ÀÁÂÃÄÅĂĄ]/g,c:/[ćčç]/g,C:/[ĆČÇ]/g,d:/[ďđ]/g,D:/[ĎÐ]/g,e:/[èéêëěę]/g,E:/[ÈÉÊËĚĘ]/g,g:/[ğ]/g,G:/[Ğ]/g,i:/[ìíîï]/g,I:/[ÌÍÎÏ]/g,l:/[ĺľł]/g,L:/[ĹĽŁ]/g,n:/[ñňń]/g,N:/[ÑŇŃ]/g,o:/[òóôõöøő]/g,O:/[ÒÓÔÕÖØ]/g,r:/[řŕ]/g,R:/[ŘŔ]/g,s:/[ššş]/g,S:/[ŠŞŚ]/g,t:/[ťţ]/g,T:/[ŤŢ]/g,u:/[ùúûůüµ]/g,U:/[ÙÚÛŮÜ]/g,y:/[ÿý]/g,Y:/[ŸÝ]/g,z:/[žźż]/g,Z:/[ŽŹŻ]/g,th:/[þ]/g,TH:/[Þ]/g,dh:/[ð]/g,DH:/[Ð]/g,ss:/[ß]/g,oe:/[œ]/g,OE:/[Œ]/g,ae:/[æ]/g,AE:/[Æ]/g},k={" ":/[\xa0\u2002\u2003\u2009]/g,"*":/[\xb7]/g,"'":/[\u2018\u2019]/g,'"':/[\u201c\u201d]/g,"...":/[\u2026]/g,"-":/[\u2013]/g,"&raquo;":/[\uFFFD]/g},l={ms:1,s:1000,m:60000,h:3600000},g=/(\d*.?\d+)([msh]+)/;var h=function(c,a){var d=c,b;for(b in a){d=d.replace(a[b],b)}return d};var i=function(d,b){d=d||"";var a=b?"<"+d+"(?!\\w)[^>]*>([\\s\\S]*?)</"+d+"(?!\\w)>":"</?"+d+"([^>]+)?>",c=new RegExp(a,"gi");return c};String.implement({standardize:function(){return h(this,j)},repeat:function(a){return new Array(a+1).join(this)},pad:function(d,a,b){if(this.length>=d){return this}var c=(a==null?" ":""+a).repeat(d-this.length).substr(0,d-this.length);if(!b||b=="right"){return this+c}if(b=="left"){return c+this}return c.substr(0,(c.length/2).floor())+this+c.substr(0,(c.length/2).ceil())},getTags:function(b,a){return this.match(i(b,a))||[]},stripTags:function(b,a){return this.replace(i(b,a),"")},tidy:function(){return h(this,k)},truncate:function(e,d,a){var b=this;if(d==null&&arguments.length==1){d="…"}if(b.length>e){b=b.substring(0,e);if(a){var c=b.lastIndexOf(a);if(c!=-1){b=b.substr(0,c)}}if(d){b+=d}}return b},ms:function(){var a=g.exec(this);if(a==null){return Number(this)}return Number(a[1])*l[a[2]]}})})();String.implement({parseQueryString:function(g,f){if(g==null){g=true}if(f==null){f=true}var h=this.split(/[&;]/),e={};if(!h.length){return e}h.each(function(a){var j=a.indexOf("=")+1,c=j?a.substr(j):"",d=j?a.substr(0,j-1).match(/([^\]\[]+|(\B)(?=\]))/g):[a],b=e;if(!d){return}if(f){c=decodeURIComponent(c)}d.each(function(m,n){if(g){m=decodeURIComponent(m)}var i=b[m];if(n<d.length-1){b=b[m]=i||{}}else{if(typeOf(i)=="array"){i.push(c)}else{b[m]=i!=null?[i,c]:c}}})});return e},cleanQueryString:function(b){return this.split("&").filter(function(f){var a=f.indexOf("="),h=a<0?"":f.substr(0,a),g=f.substr(a+1);return b?b.call(null,h,g):(g||g===0)}).join("&")}});(function(){var c=function(){return this.get("value")};var d=this.URI=new Class({Implements:Options,options:{},regex:/^(?:(\w+):)?(?:\/\/(?:(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)?(\.\.?$|(?:[^?#\/]*\/)*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,parts:["scheme","user","password","host","port","directory","file","query","fragment"],schemes:{http:80,https:443,ftp:21,rtsp:554,mms:1755,file:0},initialize:function(b,f){this.setOptions(f);var a=this.options.base||d.base;if(!b){b=a}if(b&&b.parsed){this.parsed=Object.clone(b.parsed)}else{this.set("value",b.href||b.toString(),a?new d(a):false)}},parse:function(a,b){var f=a.match(this.regex);if(!f){return false}f.shift();return this.merge(f.associate(this.parts),b)},merge:function(a,b){if((!a||!a.scheme)&&(!b||!b.scheme)){return false}if(b){this.parts.every(function(f){if(a[f]){return false}a[f]=b[f]||"";return true})}a.port=a.port||this.schemes[a.scheme.toLowerCase()];a.directory=a.directory?this.parseDirectory(a.directory,b?b.directory:""):"/";return a},parseDirectory:function(b,a){b=(b.substr(0,1)=="/"?"":(a||"/"))+b;if(!b.test(d.regs.directoryDot)){return b}var f=[];b.replace(d.regs.endSlash,"").split("/").each(function(e){if(e==".."&&f.length>0){f.pop()}else{if(e!="."){f.push(e)}}});return f.join("/")+"/"},combine:function(a){return a.value||a.scheme+"://"+(a.user?a.user+(a.password?":"+a.password:"")+"@":"")+(a.host||"")+(a.port&&a.port!=this.schemes[a.scheme]?":"+a.port:"")+(a.directory||"/")+(a.file||"")+(a.query?"?"+a.query:"")+(a.fragment?"#"+a.fragment:"")},set:function(g,a,b){if(g=="value"){var h=a.match(d.regs.scheme);if(h){h=h[1]}if(h&&this.schemes[h.toLowerCase()]==null){this.parsed={scheme:h,value:a}}else{this.parsed=this.parse(a,(b||this).parsed)||(h?{scheme:h,value:a}:{value:a})}}else{if(g=="data"){this.setData(a)}else{this.parsed[g]=a}}return this},get:function(b,a){switch(b){case"value":return this.combine(this.parsed,a?a.parsed:false);case"data":return this.getData()}return this.parsed[b]||""},go:function(){document.location.href=this.toString()},toURI:function(){return this},getData:function(b,g){var h=this.get(g||"query");if(!(h||h===0)){return b?null:{}}var a=h.parseQueryString();return b?a[b]:a},setData:function(h,a,g){if(typeof h=="string"){var b=this.getData();b[arguments[0]]=arguments[1];h=b}else{if(a){h=Object.merge(this.getData(null,g),h)}}return this.set(g||"query",Object.toQueryString(h))},clearData:function(a){return this.set(a||"query","")},toString:c,valueOf:c});d.regs={endSlash:/\/$/,scheme:/^(\w+):/,directoryDot:/\.\/|\.$/};d.base=new d(Array.from(document.getElements("base[href]",true)).getLast(),{base:document.location});String.implement({toURI:function(a){return new d(this,a)}})})();URI=Class.refactor(URI,{combine:function(m,n){if(!n||m.scheme!=n.scheme||m.host!=n.host||m.port!=n.port){return this.previous.apply(this,arguments)}var j=m.file+(m.query?"?"+m.query:"")+(m.fragment?"#"+m.fragment:"");if(!n.directory){return(m.directory||(m.file?"":"./"))+j}var o=n.directory.split("/"),p=m.directory.split("/"),l="",k;var i=0;for(k=0;k<o.length&&k<p.length&&o[k]==p[k];k++){}for(i=0;i<o.length-k-1;i++){l+="../"}for(i=k;i<p.length-1;i++){l+=p[i]+"/"}return(l||(m.file?"":"./"))+j},toAbsolute:function(b){b=new URI(b);if(b){b.set("directory","").set("file","")}return this.toRelative(b)},toRelative:function(b){return this.get("value",new URI(b))}});(function(){if(this.Hash){return}var b=this.Hash=new Type("Hash",function(a){if(typeOf(a)=="hash"){a=Object.clone(a.getClean())}for(var d in a){this[d]=a[d]}return this});this.$H=function(a){return new b(a)};b.implement({forEach:function(a,d){Object.forEach(this,a,d)},getClean:function(){var d={};for(var a in this){if(this.hasOwnProperty(a)){d[a]=this[a]}}return d},getLength:function(){var d=0;for(var a in this){if(this.hasOwnProperty(a)){d++}}return d}});b.alias("each","forEach");b.implement({has:Object.prototype.hasOwnProperty,keyOf:function(a){return Object.keyOf(this,a)},hasValue:function(a){return Object.contains(this,a)},extend:function(a){b.each(a||{},function(e,f){b.set(this,f,e)},this);return this},combine:function(a){b.each(a||{},function(e,f){b.include(this,f,e)},this);return this},erase:function(a){if(this.hasOwnProperty(a)){delete this[a]}return this},get:function(a){return(this.hasOwnProperty(a))?this[a]:null},set:function(a,d){if(!this[a]||this.hasOwnProperty(a)){this[a]=d}return this},empty:function(){b.each(this,function(d,a){delete this[a]},this);return this},include:function(a,d){if(this[a]==undefined){this[a]=d}return this},map:function(a,d){return new b(Object.map(this,a,d))},filter:function(a,d){return new b(Object.filter(this,a,d))},every:function(a,d){return Object.every(this,a,d)},some:function(a,d){return Object.some(this,a,d)},getKeys:function(){return Object.keys(this)},getValues:function(){return Object.values(this)},toQueryString:function(a){return Object.toQueryString(this,a)}});b.alias({indexOf:"keyOf",contains:"hasValue"})})();Hash.implement({getFromPath:function(b){return Object.getFromPath(this,b)},cleanValues:function(b){return new Hash(Object.cleanValues(this,b))},run:function(){Object.run(arguments)}});Element.implement({tidy:function(){this.set("value",this.get("value").tidy())},getTextInRange:function(c,d){return this.get("value").substring(c,d)},getSelectedText:function(){if(this.setSelectionRange){return this.getTextInRange(this.getSelectionStart(),this.getSelectionEnd())}return document.selection.createRange().text},getSelectedRange:function(){if(this.selectionStart!=null){return{start:this.selectionStart,end:this.selectionEnd}}var h={start:0,end:0};var g=this.getDocument().selection.createRange();if(!g||g.parentElement()!=this){return h}var j=g.duplicate();if(this.type=="text"){h.start=0-j.moveStart("character",-100000);h.end=h.start+g.text.length}else{var f=this.get("value");var i=f.length;j.moveToElementText(this);j.setEndPoint("StartToEnd",g);if(j.text.length){i-=f.match(/[\n\r]*$/)[0].length}h.end=i-j.text.length;j.setEndPoint("StartToStart",g);h.start=i-j.text.length}return h},getSelectionStart:function(){return this.getSelectedRange().start},getSelectionEnd:function(){return this.getSelectedRange().end},setCaretPosition:function(b){if(b=="end"){b=this.get("value").length}this.selectRange(b,b);return this},getCaretPosition:function(){return this.getSelectedRange().start},selectRange:function(h,g){if(this.setSelectionRange){this.focus();this.setSelectionRange(h,g)}else{var j=this.get("value");var i=j.substr(h,g-h).replace(/\r/g,"").length;h=j.substr(0,h).replace(/\r/g,"").length;var f=this.createTextRange();f.collapse(true);f.moveEnd("character",h+i);f.moveStart("character",h);f.select()}return this},insertAtCursor:function(e,f){var g=this.getSelectedRange();var h=this.get("value");this.set("value",h.substring(0,g.start)+e+h.substring(g.end,h.length));if(f!==false){this.selectRange(g.start,g.start+e.length)}else{this.setCaretPosition(g.start+e.length)}return this},insertAroundCursor:function(h,i){h=Object.append({before:"",defaultMiddle:"",after:""},h);var n=this.getSelectedText()||h.defaultMiddle;var j=this.getSelectedRange();var k=this.get("value");if(j.start==j.end){this.set("value",k.substring(0,j.start)+h.before+n+h.after+k.substring(j.end,k.length));this.selectRange(j.start+h.before.length,j.end+h.before.length+n.length)}else{var m=k.substring(j.start,j.end);this.set("value",k.substring(0,j.start)+h.before+m+h.after+k.substring(j.end,k.length));var l=j.start+h.before.length;if(i!==false){this.selectRange(l,l+m.length)}else{this.setCaretPosition(l+k.length)}}return this}});Elements.from=function(h,i){if(i||i==null){h=h.stripScripts()}var f,j=h.match(/^\s*(?:<!--.*?-->\s*)*<(t[dhr]|tbody|tfoot|thead)/i);if(j){f=new Element("table");var g=j[1].toLowerCase();if(["td","th","tr"].contains(g)){f=new Element("tbody").inject(f);if(g!="tr"){f=new Element("tr").inject(f)}}}return(f||new Element("div")).set("html",h).getChildren()};(function(){var g={relay:false},h=["once","throttle","pause"],e=h.length;while(e--){g[h[e]]=Events.lookupPseudo(h[e])}DOMEvent.definePseudo=function(b,a){g[b]=a;return this};var f=Element.prototype;[Element,Window,Document].invoke("implement",Events.Pseudos(g,f.addEvent,f.removeEvent))})();(function(){var d="$moo:keys-pressed",c="$moo:keys-keyup";DOMEvent.definePseudo("keys",function(o,n,p){var l=p[0],m=[],b=this.retrieve(d,[]),k=o.value;if(k!="+"){m.append(k.replace("++",function(){m.push("+");return""}).split("+"))}else{m=["+"]}b.include(l.key);if(m.every(function(e){return b.contains(e)})){n.apply(this,p)}this.store(d,b);if(!this.retrieve(c)){var a=function(e){(function(){b=this.retrieve(d,[]).erase(e.key);this.store(d,b)}).delay(0,this)};this.store(c,a).addEvent("keyup",a)}});DOMEvent.defineKeys({"16":"shift","17":"control","18":"alt","20":"capslock","33":"pageup","34":"pagedown","35":"end","36":"home","144":"numlock","145":"scrolllock","186":";","187":"=","188":",","190":".","191":"/","192":"`","219":"[","220":"\\","221":"]","222":"'","107":"+","109":"-","189":"-"})})();(function(){var d=function(b,c){var a=[];Object.each(c,function(h){Object.each(h,function(g){b.each(function(j){a.push(j+"-"+g+(j=="border"?"-width":""))})})});return a};var f=function(a,b){var c=0;Object.each(b,function(i,j){if(j.test(a)){c=c+i.toInt()}});return c};var e=function(a){return !!(!a||a.offsetHeight||a.offsetWidth)};Element.implement({measure:function(a){if(e(this)){return a.call(this)}var b=this.getParent(),i=[];while(!e(b)&&b!=document.body){i.push(b.expose());b=b.getParent()}var c=this.expose(),j=a.call(this);c();i.each(function(g){g()});return j},expose:function(){if(this.getStyle("display")!="none"){return function(){}}var a=this.style.cssText;this.setStyles({display:"block",position:"absolute",visibility:"hidden"});return function(){this.style.cssText=a}.bind(this)},getDimensions:function(k){k=Object.merge({computeSize:false},k);var a={x:0,y:0};var b=function(g,h){return(h.computeSize)?g.getComputedSize(h):g.getSize()};var j=this.getParent("body");if(j&&this.getStyle("display")=="none"){a=this.measure(function(){return b(this,k)})}else{if(j){try{a=b(this,k)}catch(c){}}}return Object.append(a,(a.x||a.x===0)?{width:a.x,height:a.y}:{x:a.width,y:a.height})},getComputedSize:function(h){h=Object.merge({styles:["padding","border"],planes:{height:["top","bottom"],width:["left","right"]},mode:"both"},h);var a={},c={width:0,height:0},b;if(h.mode=="vertical"){delete c.width;delete h.planes.width}else{if(h.mode=="horizontal"){delete c.height;delete h.planes.height}}d(h.styles,h.planes).each(function(g){a[g]=this.getStyle(g).toInt()},this);Object.each(h.planes,function(m,n){var g=n.capitalize(),l=this.getStyle(n);if(l=="auto"&&!b){b=this.getDimensions()}l=a[n]=(l=="auto")?b[n]:l.toInt();c["total"+g]=l;m.each(function(i){var j=f(i,a);c["computed"+i.capitalize()]=j;c["total"+g]+=j})},this);return Object.append(c,a)}})})();(function(){var e=false,d=false;var f=function(){var a=new Element("div").setStyles({position:"fixed",top:0,right:0}).inject(document.body);e=(a.offsetTop===0);a.dispose();d=true};Element.implement({pin:function(p,r){if(!d){f()}if(this.getStyle("display")=="none"){return this}var n,c=window.getScroll(),b,s;if(p!==false){n=this.getPosition();if(!this.retrieve("pin:_pinned")){var q={top:n.y-c.y,left:n.x-c.x,margin:"0px",padding:"0px"};if(e&&!r){this.setStyle("position","fixed").setStyles(q)}else{b=this.getOffsetParent();var o=this.getPosition(b),a=this.getStyles("left","top");if(b&&a.left=="auto"||a.top=="auto"){this.setPosition(o)}if(this.getStyle("position")=="static"){this.setStyle("position","absolute")}o={x:a.left.toInt()-c.x,y:a.top.toInt()-c.y};s=function(){if(!this.retrieve("pin:_pinned")){return}var g=window.getScroll();this.setStyles({left:o.x+g.x,top:o.y+g.y})}.bind(this);this.store("pin:_scrollFixer",s);window.addEvent("scroll",s)}this.store("pin:_pinned",true)}}else{if(!this.retrieve("pin:_pinned")){return this}b=this.getParent();var t=(b.getComputedStyle("position")!="static"?b:b.getOffsetParent());n=this.getPosition();this.store("pin:_pinned",false);s=this.retrieve("pin:_scrollFixer");if(!s){this.setStyles({position:"absolute",top:n.y+c.y,left:n.x+c.x})}else{this.store("pin:_scrollFixer",null);window.removeEvent("scroll",s)}this.removeClass("isPinned")}return this},unpin:function(){return this.pin(false)},togglePin:function(){return this.pin(!this.retrieve("pin:_pinned"))}})})();(function(c){var d=Element.Position={options:{relativeTo:document.body,position:{x:"center",y:"center"},offset:{x:0,y:0}},getOptions:function(a,b){b=Object.merge({},d.options,b);d.setPositionOption(b);d.setEdgeOption(b);d.setOffsetOption(a,b);d.setDimensionsOption(a,b);return b},setPositionOption:function(a){a.position=d.getCoordinateFromValue(a.position)},setEdgeOption:function(a){var b=d.getCoordinateFromValue(a.edge);a.edge=b?b:(a.position.x=="center"&&a.position.y=="center")?{x:"center",y:"center"}:{x:"left",y:"top"}},setOffsetOption:function(b,i){var j={x:0,y:0};var h={x:0,y:0};var a=b.measure(function(){return document.id(this.getOffsetParent())});if(!a||a==b.getDocument().body){return}h=a.getScroll();j=a.measure(function(){var e=this.getPosition();if(this.getStyle("position")=="fixed"){var f=window.getScroll();e.x+=f.x;e.y+=f.y}return e});i.offset={parentPositioned:a!=document.id(i.relativeTo),x:i.offset.x-j.x+h.x,y:i.offset.y-j.y+h.y}},setDimensionsOption:function(a,b){b.dimensions=a.getDimensions({computeSize:true,styles:["padding","border","margin"]})},getPosition:function(h,i){var j={};i=d.getOptions(h,i);var b=document.id(i.relativeTo)||document.body;d.setPositionCoordinates(i,j,b);if(i.edge){d.toEdge(j,i)}var a=i.offset;j.left=((j.x>=0||a.parentPositioned||i.allowNegative)?j.x:0).toInt();j.top=((j.y>=0||a.parentPositioned||i.allowNegative)?j.y:0).toInt();d.toMinMax(j,i);if(i.relFixedPosition||b.getStyle("position")=="fixed"){d.toRelFixedPosition(b,j)}if(i.ignoreScroll){d.toIgnoreScroll(b,j)}if(i.ignoreMargins){d.toIgnoreMargins(j,i)}j.left=Math.ceil(j.left);j.top=Math.ceil(j.top);delete j.x;delete j.y;return j},setPositionCoordinates:function(a,n,q){var o=a.offset.y,m=a.offset.x,p=(q==document.body)?window.getScroll():q.getPosition(),b=p.y,r=p.x,l=window.getSize();switch(a.position.x){case"left":n.x=r+m;break;case"right":n.x=r+m+q.offsetWidth;break;default:n.x=r+((q==document.body?l.x:q.offsetWidth)/2)+m;break}switch(a.position.y){case"top":n.y=b+o;break;case"bottom":n.y=b+o+q.offsetHeight;break;default:n.y=b+((q==document.body?l.y:q.offsetHeight)/2)+o;break}},toMinMax:function(h,g){var a={left:"x",top:"y"},b;["minimum","maximum"].each(function(e){["left","top"].each(function(f){b=g[e]?g[e][a[f]]:null;if(b!=null&&((e=="minimum")?h[f]<b:h[f]>b)){h[f]=b}})})},toRelFixedPosition:function(a,f){var b=window.getScroll();f.top+=b.y;f.left+=b.x},toIgnoreScroll:function(a,b){var f=a.getScroll();b.top-=f.y;b.left-=f.x},toIgnoreMargins:function(b,a){b.left+=a.edge.x=="right"?a.dimensions["margin-right"]:(a.edge.x!="center"?-a.dimensions["margin-left"]:-a.dimensions["margin-left"]+((a.dimensions["margin-right"]+a.dimensions["margin-left"])/2));b.top+=a.edge.y=="bottom"?a.dimensions["margin-bottom"]:(a.edge.y!="center"?-a.dimensions["margin-top"]:-a.dimensions["margin-top"]+((a.dimensions["margin-bottom"]+a.dimensions["margin-top"])/2))},toEdge:function(j,i){var h={},a=i.dimensions,b=i.edge;switch(b.x){case"left":h.x=0;break;case"right":h.x=-a.x-a.computedRight-a.computedLeft;break;default:h.x=-(Math.round(a.totalWidth/2));break}switch(b.y){case"top":h.y=0;break;case"bottom":h.y=-a.y-a.computedTop-a.computedBottom;break;default:h.y=-(Math.round(a.totalHeight/2));break}j.x+=h.x;j.y+=h.y},getCoordinateFromValue:function(a){if(typeOf(a)!="string"){return a}a=a.toLowerCase();return{x:a.test("left")?"left":(a.test("right")?"right":"center"),y:a.test(/upper|top/)?"top":(a.test("bottom")?"bottom":"center")}}};Element.implement({position:function(a){if(a&&(a.x!=null||a.y!=null)){return(c?c.apply(this,arguments):this)}var b=this.setStyle("position","absolute").calculatePosition(a);return(a&&a.returnPos)?b:this.setStyles(b)},calculatePosition:function(a){return d.getPosition(this,a)}})})(Element.prototype.position);Element.implement({isDisplayed:function(){return this.getStyle("display")!="none"},isVisible:function(){var d=this.offsetWidth,c=this.offsetHeight;return(d==0&&c==0)?false:(d>0&&c>0)?true:this.style.display!="none"},toggle:function(){return this[this.isDisplayed()?"hide":"show"]()},hide:function(){var c;try{c=this.getStyle("display")}catch(d){}if(c=="none"){return this}return this.store("element:_originalDisplay",c||"").setStyle("display","none")},show:function(b){if(!b&&this.isDisplayed()){return this}b=b||this.retrieve("element:_originalDisplay")||"block";return this.setStyle("display",(b=="none")?"block":b)},swapClass:function(d,c){return this.removeClass(d).addClass(c)}});Document.implement({clearSelection:function(){if(window.getSelection){var d=window.getSelection();if(d&&d.removeAllRanges){d.removeAllRanges()}}else{if(document.selection&&document.selection.empty){try{document.selection.empty()}catch(c){}}}}});(function(){var b=false;this.IframeShim=new Class({Implements:[Options,Events,Class.Occlude],options:{className:"iframeShim",src:'javascript:false;document.write("");',display:false,zIndex:null,margin:0,offset:{x:0,y:0},browsers:b},property:"IframeShim",initialize:function(d,a){this.element=document.id(d);if(this.occlude()){return this.occluded}this.setOptions(a);this.makeShim();return this},makeShim:function(){if(this.options.browsers){var e=this.element.getStyle("zIndex").toInt();if(!e){e=1;var f=this.element.getStyle("position");if(f=="static"||!f){this.element.setStyle("position","relative")}this.element.setStyle("zIndex",e)}e=((this.options.zIndex!=null||this.options.zIndex===0)&&e>this.options.zIndex)?this.options.zIndex:e-1;if(e<0){e=1}this.shim=new Element("iframe",{src:this.options.src,scrolling:"no",frameborder:0,styles:{zIndex:e,position:"absolute",border:"none",filter:"progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"},"class":this.options.className}).store("IframeShim",this);var a=(function(){this.shim.inject(this.element,"after");this[this.options.display?"show":"hide"]();this.fireEvent("inject")}).bind(this);if(!IframeShim.ready){window.addEvent("load",a)}else{a()}}else{this.position=this.hide=this.show=this.dispose=Function.from(this)}},position:function(){if(!IframeShim.ready||!this.shim){return this}var a=this.element.measure(function(){return this.getSize()});if(this.options.margin!=undefined){a.x=a.x-(this.options.margin*2);a.y=a.y-(this.options.margin*2);this.options.offset.x+=this.options.margin;this.options.offset.y+=this.options.margin}this.shim.set({width:a.x,height:a.y}).position({relativeTo:this.element,offset:this.options.offset});return this},hide:function(){if(this.shim){this.shim.setStyle("display","none")}return this},show:function(){if(this.shim){this.shim.setStyle("display","block")}return this.position()},dispose:function(){if(this.shim){this.shim.dispose()}return this},destroy:function(){if(this.shim){this.shim.destroy()}return this}})})();window.addEvent("load",function(){IframeShim.ready=true});var Mask=new Class({Implements:[Options,Events],Binds:["position"],options:{style:{},"class":"mask",maskMargins:false,useIframeShim:true,iframeShimOptions:{}},initialize:function(c,d){this.target=document.id(c)||document.id(document.body);this.target.store("mask",this);this.setOptions(d);this.render();this.inject()},render:function(){this.element=new Element("div",{"class":this.options["class"],id:this.options.id||"mask-"+String.uniqueID(),styles:Object.merge({},this.options.style,{display:"none"}),events:{click:function(b){this.fireEvent("click",b);if(this.options.hideOnClick){this.hide()}}.bind(this)}});this.hidden=true},toElement:function(){return this.element},inject:function(c,d){d=d||(this.options.inject?this.options.inject.where:"")||(this.target==document.body?"inside":"after");c=c||(this.options.inject&&this.options.inject.target)||this.target;this.element.inject(c,d);if(this.options.useIframeShim){this.shim=new IframeShim(this.element,this.options.iframeShimOptions);this.addEvents({show:this.shim.show.bind(this.shim),hide:this.shim.hide.bind(this.shim),destroy:this.shim.destroy.bind(this.shim)})}},position:function(){this.resize(this.options.width,this.options.height);this.element.position({relativeTo:this.target,position:"topLeft",ignoreMargins:!this.options.maskMargins,ignoreScroll:this.target==document.body});return this},resize:function(g,h){var f={styles:["padding","border"]};if(this.options.maskMargins){f.styles.push("margin")}var i=this.target.getComputedSize(f);if(this.target==document.body){this.element.setStyles({width:0,height:0});var j=window.getScrollSize();if(i.totalHeight<j.y){i.totalHeight=j.y}if(i.totalWidth<j.x){i.totalWidth=j.x}}this.element.setStyles({width:Array.pick([g,i.totalWidth,i.x]),height:Array.pick([h,i.totalHeight,i.y])});return this},show:function(){if(!this.hidden){return this}window.addEvent("resize",this.position);this.position();this.showMask.apply(this,arguments);return this},showMask:function(){this.element.setStyle("display","block");this.hidden=false;this.fireEvent("show")},hide:function(){if(this.hidden){return this}window.removeEvent("resize",this.position);this.hideMask.apply(this,arguments);if(this.options.destroyOnHide){return this.destroy()}return this},hideMask:function(){this.element.setStyle("display","none");this.hidden=true;this.fireEvent("hide")},toggle:function(){this[this.hidden?"show":"hide"]()},destroy:function(){this.hide();this.element.destroy();this.fireEvent("destroy");this.target.eliminate("mask")}});Element.Properties.mask={set:function(c){var d=this.retrieve("mask");if(d){d.destroy()}return this.eliminate("mask").store("mask:options",c)},get:function(){var b=this.retrieve("mask");if(!b){b=new Mask(this,this.retrieve("mask:options"));this.store("mask",b)}return b}};Element.implement({mask:function(b){if(b){this.set("mask",b)}this.get("mask").show();return this},unmask:function(){this.get("mask").hide();return this}});var Spinner=new Class({Extends:Mask,Implements:Chain,options:{"class":"spinner",containerPosition:{},content:{"class":"spinner-content"},messageContainer:{"class":"spinner-msg"},img:{"class":"spinner-img"},fxOptions:{link:"chain"}},initialize:function(f,e){this.target=document.id(f)||document.id(document.body);this.target.store("spinner",this);this.setOptions(e);this.render();this.inject();var d=function(){this.active=false}.bind(this);this.addEvents({hide:d,show:d})},render:function(){this.parent();this.element.set("id",this.options.id||"spinner-"+String.uniqueID());this.content=document.id(this.options.content)||new Element("div",this.options.content);this.content.inject(this.element);if(this.options.message){this.msg=document.id(this.options.message)||new Element("p",this.options.messageContainer).appendText(this.options.message);this.msg.inject(this.content)}if(this.options.img){this.img=document.id(this.options.img)||new Element("div",this.options.img);this.img.inject(this.content)}this.element.set("tween",this.options.fxOptions)},show:function(b){if(this.active){return this.chain(this.show.bind(this))}if(!this.hidden){this.callChain.delay(20,this);return this}this.target.set("aria-busy","true");this.active=true;return this.parent(b)},showMask:function(d){var c=function(){this.content.position(Object.merge({relativeTo:this.element},this.options.containerPosition))}.bind(this);if(d){this.parent();c()}else{if(!this.options.style.opacity){this.options.style.opacity=this.element.getStyle("opacity").toFloat()}this.element.setStyles({display:"block",opacity:0}).tween("opacity",this.options.style.opacity);c();this.hidden=false;this.fireEvent("show");this.callChain()}},hide:function(b){if(this.active){return this.chain(this.hide.bind(this))}if(this.hidden){this.callChain.delay(20,this);return this}this.target.set("aria-busy","false");this.active=true;return this.parent(b)},hideMask:function(b){if(b){return this.parent()}this.element.tween("opacity",0).get("tween").chain(function(){this.element.setStyle("display","none");this.hidden=true;this.fireEvent("hide");this.callChain()}.bind(this))},destroy:function(){this.content.destroy();this.parent();this.target.eliminate("spinner")}});Request=Class.refactor(Request,{options:{useSpinner:false,spinnerOptions:{},spinnerTarget:false},initialize:function(b){this._send=this.send;this.send=function(a){var d=this.getSpinner();if(d){d.chain(this._send.pass(a,this)).show()}else{this._send(a)}return this};this.previous(b)},getSpinner:function(){if(!this.spinner){var c=document.id(this.options.spinnerTarget)||document.id(this.options.update);if(this.options.useSpinner&&c){c.set("spinner",this.options.spinnerOptions);var d=this.spinner=c.get("spinner");["complete","exception","cancel"].each(function(a){this.addEvent(a,d.hide.bind(d))},this)}}return this.spinner}});Element.Properties.spinner={set:function(d){var c=this.retrieve("spinner");if(c){c.destroy()}return this.eliminate("spinner").store("spinner:options",d)},get:function(){var b=this.retrieve("spinner");if(!b){b=new Spinner(this,this.retrieve("spinner:options"));this.store("spinner",b)}return b}};Element.implement({spin:function(b){if(b){this.set("spinner",b)}this.get("spinner").show();return this},unspin:function(){this.get("spinner").hide();return this}});if(!window.Form){window.Form={}}(function(){Form.Request=new Class({Binds:["onSubmit","onFormValidate"],Implements:[Options,Events,Class.Occlude],options:{requestOptions:{evalScripts:true,useSpinner:true,emulation:false,link:"ignore"},sendButtonClicked:true,extraData:{},resetForm:true},property:"form.request",initialize:function(d,f,e){this.element=document.id(d);if(this.occlude()){return this.occluded}this.setOptions(e).setTarget(f).attach()},setTarget:function(b){this.target=document.id(b);if(!this.request){this.makeRequest()}else{this.request.setOptions({update:this.target})}return this},toElement:function(){return this.element},makeRequest:function(){var b=this;this.request=new Request.HTML(Object.merge({update:this.target,emulation:false,spinnerTarget:this.element,method:this.element.get("method")||"post"},this.options.requestOptions)).addEvents({success:function(h,f,g,a){["complete","success"].each(function(c){b.fireEvent(c,[b.target,h,f,g,a])})},failure:function(){b.fireEvent("complete",arguments).fireEvent("failure",arguments)},exception:function(){b.fireEvent("failure",arguments)}});return this.attachReset()},attachReset:function(){if(!this.options.resetForm){return this}this.request.addEvent("success",function(){Function.attempt(function(){this.element.reset()}.bind(this));if(window.OverText){OverText.update()}}.bind(this));return this},attach:function(e){var f=(e!=false)?"addEvent":"removeEvent";this.element[f]("click:relay(button, input[type=submit])",this.saveClickedButton.bind(this));var d=this.element.retrieve("validator");if(d){d[f]("onFormValidate",this.onFormValidate)}else{this.element[f]("submit",this.onSubmit)}return this},detach:function(){return this.attach(false)},enable:function(){return this.attach()},disable:function(){return this.detach()},onFormValidate:function(h,e,f){if(!f){return}var g=this.element.retrieve("validator");if(h||(g&&!g.options.stopOnFailure)){f.stop();this.send()}},onSubmit:function(d){var c=this.element.retrieve("validator");if(c){this.element.removeEvent("submit",this.onSubmit);c.addEvent("onFormValidate",this.onFormValidate);c.validate(d);return}if(d){d.stop()}this.send()},saveClickedButton:function(d,f){var e=f.get("name");if(!e||!this.options.sendButtonClicked){return}this.options.extraData[e]=f.get("value")||true;this.clickedCleaner=function(){delete this.options.extraData[e];this.clickedCleaner=function(){}}.bind(this)},clickedCleaner:function(){},send:function(){var c=this.element.toQueryString().trim(),d=Object.toQueryString(this.options.extraData);if(c){c+="&"+d}else{c=d}this.fireEvent("send",[this.element,c.parseQueryString()]);this.request.send({data:c,url:this.options.requestOptions.url||this.element.get("action")});this.clickedCleaner();return this}});Element.implement("formUpdate",function(f,d){var e=this.retrieve("form.request");if(!e){e=new Form.Request(this,f,d)}else{if(f){e.setTarget(f)}if(d){e.setOptions(d).makeRequest()}}e.send();return this})})();(function(){var b=function(e){var a=e.options.hideInputs;if(window.OverText){var f=[null];OverText.each(function(c){f.include("."+c.options.labelClass)});if(f){a+=f.join(", ")}}return(a)?e.element.getElements(a):null};Fx.Reveal=new Class({Extends:Fx.Morph,options:{link:"cancel",styles:["padding","border","margin"],transitionOpacity:"opacity" in document.documentElement,mode:"vertical",display:function(){return this.element.get("tag")!="tr"?"block":"table-row"},opacity:1,hideInputs:!("opacity" in document.documentElement)?"select, input, textarea, object, embed":null},dissolve:function(){if(!this.hiding&&!this.showing){if(this.element.getStyle("display")!="none"){this.hiding=true;this.showing=false;this.hidden=true;this.cssText=this.element.style.cssText;var e=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode});if(this.options.transitionOpacity){e.opacity=this.options.opacity}var f={};Object.each(e,function(c,d){f[d]=[c,0]});this.element.setStyles({display:Function.from(this.options.display).call(this),overflow:"hidden"});var a=b(this);if(a){a.setStyle("visibility","hidden")}this.$chain.unshift(function(){if(this.hidden){this.hiding=false;this.element.style.cssText=this.cssText;this.element.setStyle("display","none");if(a){a.setStyle("visibility","visible")}}this.fireEvent("hide",this.element);this.callChain()}.bind(this));this.start(f)}else{this.callChain.delay(10,this);this.fireEvent("complete",this.element);this.fireEvent("hide",this.element)}}else{if(this.options.link=="chain"){this.chain(this.dissolve.bind(this))}else{if(this.options.link=="cancel"&&!this.hiding){this.cancel();this.dissolve()}}}return this},reveal:function(){if(!this.showing&&!this.hiding){if(this.element.getStyle("display")=="none"){this.hiding=false;this.showing=true;this.hidden=false;this.cssText=this.element.style.cssText;var e;this.element.measure(function(){e=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode})}.bind(this));if(this.options.heightOverride!=null){e.height=this.options.heightOverride.toInt()}if(this.options.widthOverride!=null){e.width=this.options.widthOverride.toInt()}if(this.options.transitionOpacity){this.element.setStyle("opacity",0);e.opacity=this.options.opacity}var f={height:0,display:Function.from(this.options.display).call(this)};Object.each(e,function(c,d){f[d]=0});f.overflow="hidden";this.element.setStyles(f);var a=b(this);if(a){a.setStyle("visibility","hidden")}this.$chain.unshift(function(){this.element.style.cssText=this.cssText;this.element.setStyle("display",Function.from(this.options.display).call(this));if(!this.hidden){this.showing=false}if(a){a.setStyle("visibility","visible")}this.callChain();this.fireEvent("show",this.element)}.bind(this));this.start(e)}else{this.callChain();this.fireEvent("complete",this.element);this.fireEvent("show",this.element)}}else{if(this.options.link=="chain"){this.chain(this.reveal.bind(this))}else{if(this.options.link=="cancel"&&!this.showing){this.cancel();this.reveal()}}}return this},toggle:function(){if(this.element.getStyle("display")=="none"){this.reveal()}else{this.dissolve()}return this},cancel:function(){this.parent.apply(this,arguments);if(this.cssText!=null){this.element.style.cssText=this.cssText}this.hiding=false;this.showing=false;return this}});Element.Properties.reveal={set:function(a){this.get("reveal").cancel().setOptions(a);return this},get:function(){var a=this.retrieve("reveal");if(!a){a=new Fx.Reveal(this);this.store("reveal",a)}return a}};Element.Properties.dissolve=Element.Properties.reveal;Element.implement({reveal:function(a){this.get("reveal").setOptions(a).reveal();return this},dissolve:function(a){this.get("reveal").setOptions(a).dissolve();return this},nix:function(a){var d=Array.link(arguments,{destroy:Type.isBoolean,options:Type.isObject});this.get("reveal").setOptions(a).dissolve().chain(function(){this[d.destroy?"destroy":"dispose"]()}.bind(this));return this},wink:function(){var d=Array.link(arguments,{duration:Type.isNumber,options:Type.isObject});var a=this.get("reveal").setOptions(d.options);a.reveal().chain(function(){(function(){a.dissolve()}).delay(d.duration||2000)})}})})();Form.Request.Append=new Class({Extends:Form.Request,options:{useReveal:true,revealOptions:{},inject:"bottom"},makeRequest:function(){this.request=new Request.HTML(Object.merge({url:this.element.get("action"),method:this.element.get("method")||"post",spinnerTarget:this.element},this.options.requestOptions,{evalScripts:false})).addEvents({success:function(h,j,k,i){var n;var m=Elements.from(k);if(m.length==1){n=m[0]}else{n=new Element("div",{styles:{display:"none"}}).adopt(m)}n.inject(this.target,this.options.inject);if(this.options.requestOptions.evalScripts){Browser.exec(i)}this.fireEvent("beforeEffect",n);var l=function(){this.fireEvent("success",[n,this.target,h,j,k,i])}.bind(this);if(this.options.useReveal){n.set("reveal",this.options.revealOptions).get("reveal").chain(l);n.reveal()}else{l()}}.bind(this),failure:function(b){this.fireEvent("failure",b)}.bind(this)});this.attachReset()}});Locale.define("en-US","FormValidator",{required:"This field is required.",length:"Please enter {length} characters (you entered {elLength} characters)",minLength:"Please enter at least {minLength} characters (you entered {length} characters).",maxLength:"Please enter no more than {maxLength} characters (you entered {length} characters).",integer:"Please enter an integer in this field. Numbers with decimals (e.g. 1.25) are not permitted.",numeric:'Please enter only numeric values in this field (i.e. "1" or "1.1" or "-1" or "-1.1").',digits:"Please use numbers and punctuation only in this field (for example, a phone number with dashes or dots is permitted).",alpha:"Please use only letters (a-z) within this field. No spaces or other characters are allowed.",alphanum:"Please use only letters (a-z) or numbers (0-9) in this field. No spaces or other characters are allowed.",dateSuchAs:"Please enter a valid date such as {date}",dateInFormatMDY:'Please enter a valid date such as MM/DD/YYYY (i.e. "12/31/1999")',email:'Please enter a valid email address. For example "fred@domain.com".',url:"Please enter a valid URL such as http://www.example.com.",currencyDollar:"Please enter a valid $ amount. For example $100.00 .",oneRequired:"Please enter something for at least one of these inputs.",errorPrefix:"Error: ",warningPrefix:"Warning: ",noSpace:"There can be no spaces in this input.",reqChkByNode:"No items are selected.",requiredChk:"This field is required.",reqChkByName:"Please select a {label}.",match:"This field needs to match the {matchName} field",startDate:"the start date",endDate:"the end date",currentDate:"the current date",afterDate:"The date should be the same or after {label}.",beforeDate:"The date should be the same or before {label}.",startMonth:"Please select a start month",sameMonth:"These two dates must be in the same month - you must change one or the other.",creditcard:"The credit card number entered is invalid. Please check the number and try again. {length} digits entered."});if(!window.Form){window.Form={}}var InputValidator=this.InputValidator=new Class({Implements:[Options],options:{errorMsg:"Validation failed.",test:Function.from(true)},initialize:function(c,d){this.setOptions(d);this.className=c},test:function(c,d){c=document.id(c);return(c)?this.options.test(c,d||this.getProps(c)):false},getError:function(f,e){f=document.id(f);var d=this.options.errorMsg;if(typeOf(d)=="function"){d=d(f,e||this.getProps(f))}return d},getProps:function(b){b=document.id(b);return(b)?b.get("validatorProps"):{}}});Element.Properties.validators={get:function(){return(this.get("data-validators")||this.className).clean().split(" ")}};Element.Properties.validatorProps={set:function(b){return this.eliminate("$moo:validatorProps").store("$moo:validatorProps",b)},get:function(e){if(e){this.set(e)}if(this.retrieve("$moo:validatorProps")){return this.retrieve("$moo:validatorProps")}if(this.getProperty("data-validator-properties")||this.getProperty("validatorProps")){try{this.store("$moo:validatorProps",JSON.decode(this.getProperty("validatorProps")||this.getProperty("data-validator-properties"),false))}catch(f){return{}}}else{var d=this.get("validators").filter(function(a){return a.test(":")});if(!d.length){this.store("$moo:validatorProps",{})}else{e={};d.each(function(c){var b=c.split(":");if(b[1]){try{e[b[0]]=JSON.decode(b[1])}catch(a){}}});this.store("$moo:validatorProps",e)}}return this.retrieve("$moo:validatorProps")}};Form.Validator=new Class({Implements:[Options,Events],options:{fieldSelectors:"input, select, textarea",ignoreHidden:true,ignoreDisabled:true,useTitles:false,evaluateOnSubmit:true,evaluateFieldsOnBlur:true,evaluateFieldsOnChange:true,serial:true,stopOnFailure:true,warningPrefix:function(){return Form.Validator.getMsg("warningPrefix")||"Warning: "},errorPrefix:function(){return Form.Validator.getMsg("errorPrefix")||"Error: "}},initialize:function(c,d){this.setOptions(d);this.element=document.id(c);this.warningPrefix=Function.from(this.options.warningPrefix)();this.errorPrefix=Function.from(this.options.errorPrefix)();this._bound={onSubmit:this.onSubmit.bind(this),blurOrChange:function(b,a){this.validationMonitor(a,true)}.bind(this)};this.enable()},toElement:function(){return this.element},getFields:function(){return(this.fields=this.element.getElements(this.options.fieldSelectors))},enable:function(){this.element.store("validator",this);if(this.options.evaluateOnSubmit){this.element.addEvent("submit",this._bound.onSubmit)}if(this.options.evaluateFieldsOnBlur){this.element.addEvent("blur:relay(input,select,textarea)",this._bound.blurOrChange)}if(this.options.evaluateFieldsOnChange){this.element.addEvent("change:relay(input,select,textarea)",this._bound.blurOrChange)}},disable:function(){this.element.eliminate("validator");this.element.removeEvents({submit:this._bound.onSubmit,"blur:relay(input,select,textarea)":this._bound.blurOrChange,"change:relay(input,select,textarea)":this._bound.blurOrChange})},validationMonitor:function(){clearTimeout(this.timer);this.timer=this.validateField.delay(50,this,arguments)},onSubmit:function(b){if(this.validate(b)){this.reset()}},reset:function(){this.getFields().each(this.resetField,this);return this},validate:function(c){var d=this.getFields().map(function(a){return this.validateField(a,true)},this).every(function(a){return a});this.fireEvent("formValidate",[d,this.element,c]);if(this.options.stopOnFailure&&!d&&c){c.preventDefault()}return d},validateField:function(k,s){if(this.paused){return true}k=document.id(k);var o=!k.hasClass("validation-failed");var n,l;if(this.options.serial&&!s){n=this.element.getElement(".validation-failed");l=this.element.getElement(".warning")}if(k&&(!n||s||k.hasClass("validation-failed")||(n&&!this.options.serial))){var t=k.get("validators");var q=t.some(function(a){return this.getValidator(a)},this);var m=[];t.each(function(a){if(a&&!this.test(a,k)){m.include(a)}},this);o=m.length===0;if(q&&!this.hasValidator(k,"warnOnly")){if(o){k.addClass("validation-passed").removeClass("validation-failed");this.fireEvent("elementPass",[k])}else{k.addClass("validation-failed").removeClass("validation-passed");this.fireEvent("elementFail",[k,m])}}if(!l){var p=t.some(function(a){if(a.test("^warn")){return this.getValidator(a.replace(/^warn-/,""))}else{return null}},this);k.removeClass("warning");var r=t.map(function(a){if(a.test("^warn")){return this.test(a.replace(/^warn-/,""),k,true)}else{return null}},this)}}return o},test:function(f,i,h){i=document.id(i);if((this.options.ignoreHidden&&!i.isVisible())||(this.options.ignoreDisabled&&i.get("disabled"))){return true}var g=this.getValidator(f);if(h!=null){h=false}if(this.hasValidator(i,"warnOnly")){h=true}var j=i.hasClass("ignoreValidation")||(g?g.test(i):true);if(g){this.fireEvent("elementValidate",[j,i,f,h])}if(h){return true}return j},hasValidator:function(c,d){return c.get("validators").contains(d)},resetField:function(b){b=document.id(b);if(b){b.get("validators").each(function(a){if(a.test("^warn-")){a=a.replace(/^warn-/,"")}b.removeClass("validation-failed");b.removeClass("warning");b.removeClass("validation-passed")},this)}return this},stop:function(){this.paused=true;return this},start:function(){this.paused=false;return this},ignoreField:function(d,c){d=document.id(d);if(d){this.enforceField(d);if(c){d.addClass("warnOnly")}else{d.addClass("ignoreValidation")}}return this},enforceField:function(b){b=document.id(b);if(b){b.removeClass("warnOnly").removeClass("ignoreValidation")}return this}});Form.Validator.getMsg=function(b){return Locale.get("FormValidator."+b)};Form.Validator.adders={validators:{},add:function(c,d){this.validators[c]=new InputValidator(c,d);if(!this.initialize){this.implement({validators:this.validators})}},addAllThese:function(b){Array.from(b).each(function(a){this.add(a[0],a[1])},this)},getValidator:function(b){return this.validators[b.split(":")[0]]}};Object.append(Form.Validator,Form.Validator.adders);Form.Validator.implement(Form.Validator.adders);Form.Validator.add("IsEmpty",{errorMsg:false,test:function(b){if(b.type=="select-one"||b.type=="select"){return !(b.selectedIndex>=0&&b.options[b.selectedIndex].value!="")}else{return((b.get("value")==null)||(b.get("value").length==0))}}});Form.Validator.addAllThese([["required",{errorMsg:function(){return Form.Validator.getMsg("required")},test:function(b){return !Form.Validator.getValidator("IsEmpty").test(b)}}],["length",{errorMsg:function(d,c){if(typeOf(c.length)!="null"){return Form.Validator.getMsg("length").substitute({length:c.length,elLength:d.get("value").length})}else{return""}},test:function(d,c){if(typeOf(c.length)!="null"){return(d.get("value").length==c.length||d.get("value").length==0)}else{return true}}}],["minLength",{errorMsg:function(d,c){if(typeOf(c.minLength)!="null"){return Form.Validator.getMsg("minLength").substitute({minLength:c.minLength,length:d.get("value").length})}else{return""}},test:function(d,c){if(typeOf(c.minLength)!="null"){return(d.get("value").length>=(c.minLength||0))}else{return true}}}],["maxLength",{errorMsg:function(d,c){if(typeOf(c.maxLength)!="null"){return Form.Validator.getMsg("maxLength").substitute({maxLength:c.maxLength,length:d.get("value").length})}else{return""}},test:function(d,c){return d.get("value").length<=(c.maxLength||10000)}}],["validate-integer",{errorMsg:Form.Validator.getMsg.pass("integer"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^(-?[1-9]\d*|0)$/).test(b.get("value"))}}],["validate-numeric",{errorMsg:Form.Validator.getMsg.pass("numeric"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(b.get("value"))}}],["validate-digits",{errorMsg:Form.Validator.getMsg.pass("digits"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^[\d() .:\-\+#]+$/.test(b.get("value")))}}],["validate-alpha",{errorMsg:Form.Validator.getMsg.pass("alpha"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^[a-zA-Z]+$/).test(b.get("value"))}}],["validate-alphanum",{errorMsg:Form.Validator.getMsg.pass("alphanum"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||!(/\W/).test(b.get("value"))}}],["validate-date",{errorMsg:function(e,d){if(Date.parse){var f=d.dateFormat||"%x";return Form.Validator.getMsg("dateSuchAs").substitute({date:new Date().format(f)})}else{return Form.Validator.getMsg("dateInFormatMDY")}},test:function(n,l){if(Form.Validator.getValidator("IsEmpty").test(n)){return true}var r=Locale.get("Date"),q=new RegExp([r.days,r.days_abbr,r.months,r.months_abbr,r.AM,r.PM].flatten().join("|"),"i"),j=n.get("value"),m=j.match(/[a-z]+/gi);if(m&&!m.every(q.exec,q)){return false}var p=Date.parse(j),k=l.dateFormat||"%x",o=p.format(k);if(o!="invalid date"){n.set("value",o)}return p.isValid()}}],["validate-email",{errorMsg:Form.Validator.getMsg.pass("email"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+\/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(b.get("value"))}}],["validate-url",{errorMsg:Form.Validator.getMsg.pass("url"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i).test(b.get("value"))}}],["validate-currency-dollar",{errorMsg:Form.Validator.getMsg.pass("currencyDollar"),test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(b.get("value"))}}],["validate-one-required",{errorMsg:Form.Validator.getMsg.pass("oneRequired"),test:function(e,d){var f=document.id(d["validate-one-required"])||e.getParent(d["validate-one-required"]);return f.getElements("input").some(function(a){if(["checkbox","radio"].contains(a.get("type"))){return a.get("checked")}return a.get("value")})}}]]);Element.Properties.validator={set:function(b){this.get("validator").setOptions(b)},get:function(){var b=this.retrieve("validator");if(!b){b=new Form.Validator(this);this.store("validator",b)}return b}};Element.implement({validate:function(b){if(b){this.set("validator",b)}return this.get("validator").validate()}});Form.Validator.Inline=new Class({Extends:Form.Validator,options:{showError:function(b){if(b.reveal){b.reveal()}else{b.setStyle("display","block")}},hideError:function(b){if(b.dissolve){b.dissolve()}else{b.setStyle("display","none")}},scrollToErrorsOnSubmit:true,scrollToErrorsOnBlur:false,scrollToErrorsOnChange:false,scrollFxOptions:{transition:"quad:out",offset:{y:-20}}},initialize:function(c,d){this.parent(c,d);this.addEvent("onElementValidate",function(b,i,j,a){var k=this.getValidator(j);if(!b&&k.getError(i)){if(a){i.addClass("warning")}var l=this.makeAdvice(j,i,k.getError(i),a);this.insertAdvice(l,i);this.showAdvice(j,i)}else{this.hideAdvice(j,i)}})},makeAdvice:function(m,k,n,j){var l=(j)?this.warningPrefix:this.errorPrefix;l+=(this.options.useTitles)?k.title||n:n;var i=(j)?"warning-advice":"validation-advice";var h=this.getAdvice(m,k);if(h){h=h.set("html",l)}else{h=new Element("div",{html:l,styles:{display:"none"},id:"advice-"+m.split(":")[0]+"-"+this.getFieldId(k)}).addClass(i)}k.store("$moo:advice-"+m,h);return h},getFieldId:function(b){return b.id?b.id:b.id="input_"+b.name},showAdvice:function(d,f){var e=this.getAdvice(d,f);if(e&&!f.retrieve("$moo:"+this.getPropName(d))&&(e.getStyle("display")=="none"||e.getStyle("visibility")=="hidden"||e.getStyle("opacity")==0)){f.store("$moo:"+this.getPropName(d),true);this.options.showError(e);this.fireEvent("showAdvice",[f,e,d])}},hideAdvice:function(d,f){var e=this.getAdvice(d,f);if(e&&f.retrieve("$moo:"+this.getPropName(d))){f.store("$moo:"+this.getPropName(d),false);this.options.hideError(e);this.fireEvent("hideAdvice",[f,e,d])}},getPropName:function(b){return"advice"+b},resetField:function(b){b=document.id(b);if(!b){return this}this.parent(b);b.get("validators").each(function(a){this.hideAdvice(a,b)},this);return this},getAllAdviceMessages:function(g,h){var e=[];if(g.hasClass("ignoreValidation")&&!h){return e}var f=g.get("validators").some(function(a){var c=a.test("^warn-")||g.hasClass("warnOnly");if(c){a=a.replace(/^warn-/,"")}var b=this.getValidator(a);if(!b){return}e.push({message:b.getError(g),warnOnly:c,passed:b.test(),validator:b})},this);return e},getAdvice:function(d,c){return c.retrieve("$moo:advice-"+d)},insertAdvice:function(e,f){var d=f.get("validatorProps");if(!d.msgPos||!document.id(d.msgPos)){if(f.type&&f.type.toLowerCase()=="radio"){f.getParent().adopt(e)}else{e.inject(document.id(f),"after")}}else{document.id(d.msgPos).grab(e)}},validateField:function(j,k,h){var i=this.parent(j,k);if(((this.options.scrollToErrorsOnSubmit&&h==null)||h)&&!i){var n=document.id(this).getElement(".validation-failed");var m=document.id(this).getParent();while(m!=document.body&&m.getScrollSize().y==m.getSize().y){m=m.getParent()}var l=m.retrieve("$moo:fvScroller");if(!l&&window.Fx&&Fx.Scroll){l=new Fx.Scroll(m,this.options.scrollFxOptions);m.store("$moo:fvScroller",l)}if(n){if(l){l.toElement(n)}else{m.scrollTo(m.getScroll().x,n.getPosition(m).y-20)}}}return i},watchFields:function(b){b.each(function(a){if(this.options.evaluateFieldsOnBlur){a.addEvent("blur",this.validationMonitor.pass([a,false,this.options.scrollToErrorsOnBlur],this))}if(this.options.evaluateFieldsOnChange){a.addEvent("change",this.validationMonitor.pass([a,true,this.options.scrollToErrorsOnChange],this))}},this)}});Form.Validator.addAllThese([["validate-enforce-oncheck",{test:function(e,d){var f=e.getParent("form").retrieve("validator");if(!f){return true}(d.toEnforce||document.id(d.enforceChildrenOf).getElements("input, select, textarea")).map(function(a){if(e.checked){f.enforceField(a)}else{f.ignoreField(a);f.resetField(a)}});return true}}],["validate-ignore-oncheck",{test:function(e,d){var f=e.getParent("form").retrieve("validator");if(!f){return true}(d.toIgnore||document.id(d.ignoreChildrenOf).getElements("input, select, textarea")).each(function(a){if(e.checked){f.ignoreField(a);f.resetField(a)}else{f.enforceField(a)}});return true}}],["validate-nospace",{errorMsg:function(){return Form.Validator.getMsg("noSpace")},test:function(d,c){return !d.get("value").test(/\s/)}}],["validate-toggle-oncheck",{test:function(e,h){var g=e.getParent("form").retrieve("validator");if(!g){return true}var f=h.toToggle||document.id(h.toToggleChildrenOf).getElements("input, select, textarea");if(!e.checked){f.each(function(a){g.ignoreField(a);g.resetField(a)})}else{f.each(function(a){g.enforceField(a)})}return true}}],["validate-reqchk-bynode",{errorMsg:function(){return Form.Validator.getMsg("reqChkByNode")},test:function(d,c){return(document.id(c.nodeId).getElements(c.selector||"input[type=checkbox], input[type=radio]")).some(function(a){return a.checked})}}],["validate-required-check",{errorMsg:function(d,c){return c.useTitle?d.get("title"):Form.Validator.getMsg("requiredChk")},test:function(d,c){return !!d.checked}}],["validate-reqchk-byname",{errorMsg:function(d,c){return Form.Validator.getMsg("reqChkByName").substitute({label:c.label||d.get("type")})},test:function(f,i){var j=i.groupName||f.get("name");var g=$$(document.getElementsByName(j)).some(function(a,b){return a.checked});var h=f.getParent("form").retrieve("validator");if(g&&h){h.resetField(f)}return g}}],["validate-match",{errorMsg:function(d,c){return Form.Validator.getMsg("match").substitute({matchName:c.matchName||document.id(c.matchInput).get("name")})},test:function(e,h){var g=e.get("value");var f=document.id(h.matchInput)&&document.id(h.matchInput).get("value");return g&&f?g==f:true}}],["validate-after-date",{errorMsg:function(d,c){return Form.Validator.getMsg("afterDate").substitute({label:c.afterLabel||(c.afterElement?Form.Validator.getMsg("startDate"):Form.Validator.getMsg("currentDate"))})},test:function(e,h){var g=document.id(h.afterElement)?Date.parse(document.id(h.afterElement).get("value")):new Date();var f=Date.parse(e.get("value"));return f&&g?f>=g:true}}],["validate-before-date",{errorMsg:function(d,c){return Form.Validator.getMsg("beforeDate").substitute({label:c.beforeLabel||(c.beforeElement?Form.Validator.getMsg("endDate"):Form.Validator.getMsg("currentDate"))})},test:function(e,h){var g=Date.parse(e.get("value"));var f=document.id(h.beforeElement)?Date.parse(document.id(h.beforeElement).get("value")):new Date();return f&&g?f>=g:true}}],["validate-custom-required",{errorMsg:function(){return Form.Validator.getMsg("required")},test:function(d,c){return d.get("value")!=c.emptyValue}}],["validate-same-month",{errorMsg:function(f,e){var h=document.id(e.sameMonthAs)&&document.id(e.sameMonthAs).get("value");var g=f.get("value");if(g!=""){return Form.Validator.getMsg(h?"sameMonth":"startMonth")}},test:function(f,e){var g=Date.parse(f.get("value"));var h=Date.parse(document.id(e.sameMonthAs)&&document.id(e.sameMonthAs).get("value"));return g&&h?g.format("%B")==h.format("%B"):true}}],["validate-cc-num",{errorMsg:function(d){var c=d.get("value").replace(/[^0-9]/g,"");return Form.Validator.getMsg("creditcard").substitute({length:c.length})},test:function(n){if(Form.Validator.getValidator("IsEmpty").test(n)){return true}var j=n.get("value");j=j.replace(/[^0-9]/g,"");var i=false;if(j.test(/^4[0-9]{12}([0-9]{3})?$/)){i="Visa"}else{if(j.test(/^5[1-5]([0-9]{14})$/)){i="Master Card"}else{if(j.test(/^3[47][0-9]{13}$/)){i="American Express"}else{if(j.test(/^6011[0-9]{12}$/)){i="Discover"}}}}if(i){var m=0;var l=0;for(var h=j.length-1;h>=0;--h){l=j.charAt(h).toInt();if(l==0){continue}if((j.length-h)%2==0){l+=l}if(l>9){l=l.toString().charAt(0).toInt()+l.toString().charAt(1).toInt()}m+=l}if((m%10)==0){return true}}var k="";while(j!=""){k+=" "+j.substr(0,4);j=j.substr(4)}n.getParent("form").retrieve("validator").ignoreField(n);n.set("value",k.clean());n.getParent("form").retrieve("validator").enforceField(n);return false}}]]);var OverText=new Class({Implements:[Options,Events,Class.Occlude],Binds:["reposition","assert","focus","hide"],options:{element:"label",labelClass:"overTxtLabel",positionOptions:{position:"upperLeft",edge:"upperLeft",offset:{x:4,y:2}},poll:false,pollInterval:250,wrap:false},property:"OverText",initialize:function(c,d){c=this.element=document.id(c);if(this.occlude()){return this.occluded}this.setOptions(d);this.attach(c);OverText.instances.push(this);if(this.options.poll){this.poll()}},toElement:function(){return this.element},attach:function(){var e=this.element,f=this.options,h=f.textOverride||e.get("alt")||e.get("title");if(!h){return this}var g=this.text=new Element(f.element,{"class":f.labelClass,styles:{lineHeight:"normal",position:"absolute",cursor:"text"},html:h,events:{click:this.hide.pass(f.element=="label",this)}}).inject(e,"after");if(f.element=="label"){if(!e.get("id")){e.set("id","input_"+String.uniqueID())}g.set("for",e.get("id"))}if(f.wrap){this.textHolder=new Element("div.overTxtWrapper",{styles:{lineHeight:"normal",position:"relative"}}).grab(g).inject(e,"before")}return this.enable()},destroy:function(){this.element.eliminate(this.property);this.disable();if(this.text){this.text.destroy()}if(this.textHolder){this.textHolder.destroy()}return this},disable:function(){this.element.removeEvents({focus:this.focus,blur:this.assert,change:this.assert});window.removeEvent("resize",this.reposition);this.hide(true,true);return this},enable:function(){this.element.addEvents({focus:this.focus,blur:this.assert,change:this.assert});window.addEvent("resize",this.reposition);this.reposition();return this},wrap:function(){if(this.options.element=="label"){if(!this.element.get("id")){this.element.set("id","input_"+String.uniqueID())}this.text.set("for",this.element.get("id"))}},startPolling:function(){this.pollingPaused=false;return this.poll()},poll:function(b){if(this.poller&&!b){return this}if(b){clearInterval(this.poller)}else{this.poller=(function(){if(!this.pollingPaused){this.assert(true)}}).periodical(this.options.pollInterval,this)}return this},stopPolling:function(){this.pollingPaused=true;return this.poll(true)},focus:function(){if(this.text&&(!this.text.isDisplayed()||this.element.get("disabled"))){return this}return this.hide()},hide:function(f,e){if(this.text&&(this.text.isDisplayed()&&(!this.element.get("disabled")||e))){this.text.hide();this.fireEvent("textHide",[this.text,this.element]);this.pollingPaused=true;if(!f){try{this.element.fireEvent("focus");this.element.focus()}catch(d){}}}return this},show:function(){if(document.id(this.text)&&!this.text.isDisplayed()){this.text.show();this.reposition();this.fireEvent("textShow",[this.text,this.element]);this.pollingPaused=false}return this},test:function(){return !this.element.get("value")},assert:function(b){return this[this.test()?"show":"hide"](b)},reposition:function(){this.assert(true);if(!this.element.isVisible()){return this.stopPolling().hide()}if(this.text&&this.test()){this.text.position(Object.merge(this.options.positionOptions,{relativeTo:this.element}))}return this}});OverText.instances=[];Object.append(OverText,{each:function(b){return OverText.instances.each(function(d,a){if(d.element&&d.text){b.call(OverText,d,a)}})},update:function(){return OverText.each(function(b){return b.reposition()})},hideAll:function(){return OverText.each(function(b){return b.hide(true,true)})},showAll:function(){return OverText.each(function(b){return b.show()})}});Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(c,d){this.elements=this.subject=$$(c);this.parent(d)},compute:function(l,k,i){var p={};for(var o in l){var r=l[o],n=k[o],m=p[o]={};for(var q in r){m[q]=this.parent(r[q],n[q],i)}}return p},set:function(e){for(var h in e){if(!this.elements[h]){continue}var f=e[h];for(var g in f){this.render(this.elements[h],g,f[g],this.options.unit)}}return this},start:function(p){if(!this.check(p)){return this}var k={},i={};for(var o in p){if(!this.elements[o]){continue}var m=p[o],r=k[o]={},l=i[o]={};for(var q in m){var n=this.prepare(this.elements[o],q,m[q]);r[q]=n.from;l[q]=n.to}}return this.parent(k,i)}});Fx.Accordion=new Class({Extends:Fx.Elements,options:{fixedHeight:false,fixedWidth:false,display:0,show:false,height:true,width:false,opacity:true,alwaysHide:false,trigger:"click",initialDisplayFx:true,resetHeight:true},initialize:function(){var j=function(a){return a!=null};var k=Array.link(arguments,{container:Type.isElement,options:Type.isObject,togglers:j,elements:j});this.parent(k.elements,k.options);var h=this.options,l=this.togglers=$$(k.togglers);this.previous=-1;this.internalChain=new Chain();if(h.alwaysHide){this.options.link="chain"}if(h.show||this.options.show===0){h.display=false;this.previous=h.show}if(h.start){h.display=false;h.show=false}var m=this.effects={};if(h.opacity){m.opacity="fullOpacity"}if(h.width){m.width=h.fixedWidth?"fullWidth":"offsetWidth"}if(h.height){m.height=h.fixedHeight?"fullHeight":"scrollHeight"}for(var n=0,i=l.length;n<i;n++){this.addSection(l[n],this.elements[n])}this.elements.each(function(b,c){if(h.show===c){this.fireEvent("active",[l[c],b])}else{for(var a in m){b.setStyle(a,0)}}},this);if(h.display||h.display===0||h.initialDisplayFx===false){this.display(h.display,h.initialDisplayFx)}if(h.fixedHeight!==false){h.resetHeight=false}this.addEvent("complete",this.internalChain.callChain.bind(this.internalChain))},addSection:function(l,o){l=document.id(l);o=document.id(o);this.togglers.include(l);this.elements.include(o);var m=this.togglers,p=this.options,k=m.contains(l),j=m.indexOf(l),i=this.display.pass(j,this);l.store("accordion:display",i).addEvent(p.trigger,i);if(p.height){o.setStyles({"padding-top":0,"border-top":"none","padding-bottom":0,"border-bottom":"none"})}if(p.width){o.setStyles({"padding-left":0,"border-left":"none","padding-right":0,"border-right":"none"})}o.fullOpacity=1;if(p.fixedWidth){o.fullWidth=p.fixedWidth}if(p.fixedHeight){o.fullHeight=p.fixedHeight}o.setStyle("overflow","hidden");if(!k){for(var n in this.effects){o.setStyle(n,0)}}return this},removeSection:function(i,g){var j=this.togglers,h=j.indexOf(i),l=this.elements[h];var k=function(){j.erase(i);this.elements.erase(l);this.detach(i)}.bind(this);if(this.now==h||g!=null){this.display(g!=null?g:(h-1>=0?h-1:0)).chain(k)}else{k()}return this},detach:function(c){var d=function(a){a.removeEvent(this.options.trigger,a.retrieve("accordion:display"))}.bind(this);if(!c){this.togglers.each(d)}else{d(c)}return this},display:function(i,p){if(!this.check(i,p)){return this}var k={},l=this.elements,j=this.options,m=this.effects;if(p==null){p=true}if(typeOf(i)=="element"){i=l.indexOf(i)}if(i==this.current&&!j.alwaysHide){return this}if(j.resetHeight){var n=l[this.current];if(n&&!this.selfHidden){for(var o in m){n.setStyle(o,n[m[o]])}}}if((this.timer&&j.link=="chain")||(i===this.current&&!j.alwaysHide)){return this}if(this.current!=null){this.previous=this.current}this.current=i;this.selfHidden=false;l.each(function(b,c){k[c]={};var d;if(c!=i){d=true}else{if(j.alwaysHide&&((b.offsetHeight>0&&j.height)||b.offsetWidth>0&&j.width)){d=true;this.selfHidden=true}}this.fireEvent(d?"background":"active",[this.togglers[c],b]);for(var a in m){k[c][a]=d?0:b[m[a]]}if(!p&&!d&&j.resetHeight){k[c].height="auto"}},this);this.internalChain.clearChain();this.internalChain.chain(function(){if(j.resetHeight&&!this.selfHidden){var a=l[i];if(a){a.setStyle("height","auto")}}}.bind(this));return p?this.start(k):this.set(k).internalChain.callChain()}});Fx.Move=new Class({Extends:Fx.Morph,options:{relativeTo:document.body,position:"center",edge:false,offset:{x:0,y:0}},start:function(e){var d=this.element,f=d.getStyles("top","left");if(f.top=="auto"||f.left=="auto"){d.setPosition(d.getPosition(d.getOffsetParent()))}return this.parent(d.position(Object.merge({},this.options,e,{returnPos:true})))}});Element.Properties.move={set:function(b){this.get("move").cancel().setOptions(b);return this},get:function(){var b=this.retrieve("move");if(!b){b=new Fx.Move(this,{link:"cancel"});this.store("move",b)}return b}};Element.implement({move:function(b){this.get("move").start(b);return this}});(function(){Fx.Scroll=new Class({Extends:Fx,options:{offset:{x:0,y:0},wheelStops:true},initialize:function(h,a){this.element=this.subject=document.id(h);this.parent(a);if(typeOf(this.element)!="element"){this.element=document.id(this.element.getDocument().body)}if(this.options.wheelStops){var g=this.element,f=this.cancel.pass(false,this);this.addEvent("start",function(){g.addEvent("mousewheel",f)},true);this.addEvent("complete",function(){g.removeEvent("mousewheel",f)},true)}},set:function(){var a=Array.flatten(arguments);this.element.scrollTo(a[0],a[1]);return this},compute:function(e,f,a){return[0,1].map(function(c){return Fx.compute(e[c],f[c],a)})},start:function(f,e){if(!this.check(f,e)){return this}var a=this.element.getScroll();return this.parent([a.x,a.y],[f,e])},calculateScroll:function(m,n){var p=this.element,r=p.getScrollSize(),l=p.getScroll(),a=p.getSize(),q=this.options.offset,k={x:m,y:n};for(var o in k){if(!k[o]&&k[o]!==0){k[o]=l[o]}if(typeOf(k[o])!="number"){k[o]=r[o]-a[o]}k[o]+=q[o]}return[k.x,k.y]},toTop:function(){return this.start.apply(this,this.calculateScroll(false,0))},toLeft:function(){return this.start.apply(this,this.calculateScroll(0,false))},toRight:function(){return this.start.apply(this,this.calculateScroll("right",false))},toBottom:function(){return this.start.apply(this,this.calculateScroll(false,"bottom"))},toElement:function(g,f){f=f?Array.from(f):["x","y"];var h=b(this.element)?{x:0,y:0}:this.element.getScroll();var a=Object.map(document.id(g).getPosition(this.element),function(c,d){return f.contains(d)?c+h[d]:false});return this.start.apply(this,this.calculateScroll(a.x,a.y))},toElementEdge:function(p,m,o){m=m?Array.from(m):["x","y"];p=document.id(p);var k={},n=p.getPosition(this.element),a=p.getSize(),l=this.element.getScroll(),r=this.element.getSize(),q={x:n.x+a.x,y:n.y+a.y};["x","y"].each(function(c){if(m.contains(c)){if(q[c]>l[c]+r[c]){k[c]=q[c]-r[c]}if(n[c]<l[c]){k[c]=n[c]}}if(k[c]==null){k[c]=l[c]}if(o&&o[c]){k[c]=k[c]+o[c]}},this);if(k.x!=l.x||k.y!=l.y){this.start(k.x,k.y)}return this},toElementCenter:function(n,m,k){m=m?Array.from(m):["x","y"];n=document.id(n);var j={},p=n.getPosition(this.element),o=n.getSize(),a=this.element.getScroll(),l=this.element.getSize();["x","y"].each(function(c){if(m.contains(c)){j[c]=p[c]-(l[c]-o[c])/2}if(j[c]==null){j[c]=a[c]}if(k&&k[c]){j[c]=j[c]+k[c]}},this);if(j.x!=a.x||j.y!=a.y){this.start(j.x,j.y)}return this}});function b(a){return(/^(?:body|html)$/i).test(a.tagName)}})();Fx.Slide=new Class({Extends:Fx,options:{mode:"vertical",wrapper:false,hideOverflow:true,resetHeight:false},initialize:function(e,f){e=this.element=this.subject=document.id(e);this.parent(f);f=this.options;var g=e.retrieve("wrapper"),h=e.getStyles("margin","position","overflow");if(f.hideOverflow){h=Object.append(h,{overflow:"hidden"})}if(f.wrapper){g=document.id(f.wrapper).setStyles(h)}if(!g){g=new Element("div",{styles:h}).wraps(e)}e.store("wrapper",g).setStyle("margin",0);if(e.getStyle("overflow")=="visible"){e.setStyle("overflow","hidden")}this.now=[];this.open=true;this.wrapper=g;this.addEvent("complete",function(){this.open=(g["offset"+this.layout.capitalize()]!=0);if(this.open&&this.options.resetHeight){g.setStyle("height","")}},true)},vertical:function(){this.margin="margin-top";this.layout="height";this.offset=this.element.offsetHeight},horizontal:function(){this.margin="margin-left";this.layout="width";this.offset=this.element.offsetWidth},set:function(b){this.element.setStyle(this.margin,b[0]);this.wrapper.setStyle(this.layout,b[1]);return this},compute:function(f,d,e){return[0,1].map(function(a){return Fx.compute(f[a],d[a],e)})},start:function(h,l){if(!this.check(h,l)){return this}this[l||this.options.mode]();var m=this.element.getStyle(this.margin).toInt(),n=this.wrapper.getStyle(this.layout).toInt(),i=[[m,n],[0,this.offset]],j=[[m,n],[-this.offset,0]],k;switch(h){case"in":k=i;break;case"out":k=j;break;case"toggle":k=(n==0)?i:j}return this.parent(k[0],k[1])},slideIn:function(b){return this.start("in",b)},slideOut:function(b){return this.start("out",b)},hide:function(b){this[b||this.options.mode]();this.open=false;return this.set([-this.offset,0])},show:function(b){this[b||this.options.mode]();this.open=true;return this.set([0,this.offset])},toggle:function(b){return this.start("toggle",b)}});Element.Properties.slide={set:function(b){this.get("slide").cancel().setOptions(b);return this},get:function(){var b=this.retrieve("slide");if(!b){b=new Fx.Slide(this,{link:"cancel"});this.store("slide",b)}return b}};Element.implement({slide:function(i,h){i=i||"toggle";var f=this.get("slide"),g;switch(i){case"hide":f.hide(h);break;case"show":f.show(h);break;case"toggle":var j=this.retrieve("slide:flag",f.open);f[j?"slideOut":"slideIn"](h);this.store("slide:flag",!j);g=true;break;default:f.start(i,h)}if(!g){this.eliminate("slide:flag")}return this}});Fx.SmoothScroll=new Class({Extends:Fx.Scroll,options:{axes:["x","y"]},initialize:function(j,i){i=i||document;this.doc=i.getDocument();this.parent(this.doc,j);var h=i.getWindow(),g=h.location.href.match(/^[^#]*/)[0]+"#",f=$$(this.options.links||this.doc.links);f.each(function(a){if(a.href.indexOf(g)!=0){return}var b=a.href.substr(g.length);if(b){this.useLink(a,b)}},this);this.addEvent("complete",function(){h.location.hash=this.anchor;this.element.scrollTo(this.to[0],this.to[1])},true)},useLink:function(c,d){c.addEvent("click",function(a){var b=document.id(d)||this.doc.getElement("a[name="+d+"]");if(!b){return}a.preventDefault();this.toElement(b,this.options.axes).chain(function(){this.fireEvent("scrolledTo",[c,b])}.bind(this));this.anchor=d}.bind(this));return this}});Fx.Sort=new Class({Extends:Fx.Elements,options:{mode:"vertical"},initialize:function(c,d){this.parent(c,d);this.elements.each(function(a){if(a.getStyle("position")=="static"){a.setStyle("position","relative")}});this.setDefaultOrder()},setDefaultOrder:function(){this.currentOrder=this.elements.map(function(c,d){return d})},sort:function(){if(!this.check(arguments)){return this}var n=Array.flatten(arguments);var j=0,r=0,p={},k={},o=this.options.mode=="vertical";var m=this.elements.map(function(a,c){var b=a.getComputedSize({styles:["border","padding","margin"]});var f;if(o){f={top:j,margin:b["margin-top"],height:b.totalHeight};j+=f.height-b["margin-top"]}else{f={left:r,margin:b["margin-left"],width:b.totalWidth};r+=f.width}var d=o?"top":"left";k[c]={};var e=a.getStyle(d).toInt();k[c][d]=e||0;return f},this);this.set(k);n=n.map(function(a){return a.toInt()});if(n.length!=this.elements.length){this.currentOrder.each(function(a){if(!n.contains(a)){n.push(a)}});if(n.length>this.elements.length){n.splice(this.elements.length-1,n.length-this.elements.length)}}var q=0;j=r=0;n.each(function(a){var b={};if(o){b.top=j-m[a].top-q;j+=m[a].height}else{b.left=r-m[a].left;r+=m[a].width}q=q+m[a].margin;p[a]=b},this);var l={};Array.clone(n).sort().each(function(a){l[a]=p[a]});this.start(l);this.currentOrder=n;return this},rearrangeDOM:function(e){e=e||this.currentOrder;var d=this.elements[0].getParent();var f=[];this.elements.setStyle("opacity",0);e.each(function(a){f.push(this.elements[a].inject(d).setStyles({top:0,left:0}))},this);this.elements.setStyle("opacity",1);this.elements=$$(f);this.setDefaultOrder();return this},getDefaultOrder:function(){return this.elements.map(function(c,d){return d})},getCurrentOrder:function(){return this.currentOrder},forward:function(){return this.sort(this.getDefaultOrder())},backward:function(){return this.sort(this.getDefaultOrder().reverse())},reverse:function(){return this.sort(this.currentOrder.reverse())},sortByElements:function(b){return this.sort(b.map(function(a){return this.elements.indexOf(a)},this))},swap:function(f,d){if(typeOf(f)=="element"){f=this.elements.indexOf(f)}if(typeOf(d)=="element"){d=this.elements.indexOf(d)}var e=Array.clone(this.currentOrder);e[this.currentOrder.indexOf(f)]=d;e[this.currentOrder.indexOf(d)]=f;return this.sort(e)}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var c=Array.link(arguments,{options:Type.isObject,element:function(a){return a!=null}});this.element=document.id(c.element);this.document=this.element.getDocument();this.setOptions(c.options||{});var d=typeOf(this.options.handle);this.handles=((d=="array"||d=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element;this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection="selectstart" in document?"selectstart":"mousedown";if("ondragstart" in document&&!("FileReader" in window)&&!Drag.ondragstartFixed){document.ondragstart=Function.from(false);Drag.ondragstartFixed=true}this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:Function.from(false)};this.attach()},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this},detach:function(){this.handles.removeEvent("mousedown",this.bound.start);return this},start:function(r){var i=this.options;if(r.rightClick){return}if(i.preventDefault){r.preventDefault()}if(i.stopPropagation){r.stopPropagation()}this.mouse.start=r.page;this.fireEvent("beforeStart",this.element);var p=i.limit;this.limit={x:[],y:[]};var n,l;for(n in i.modifiers){if(!i.modifiers[n]){continue}var q=this.element.getStyle(i.modifiers[n]);if(q&&!q.match(/px$/)){if(!l){l=this.element.getCoordinates(this.element.getOffsetParent())}q=l[i.modifiers[n]]}if(i.style){this.value.now[n]=(q||0).toInt()}else{this.value.now[n]=this.element[i.modifiers[n]]}if(i.invert){this.value.now[n]*=-1}this.mouse.pos[n]=r.page[n]-this.value.now[n];if(p&&p[n]){var o=2;while(o--){var m=p[n][o];if(m||m===0){this.limit[n][o]=(typeof m=="function")?m():m}}}}if(typeOf(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}}var k={mousemove:this.bound.check,mouseup:this.bound.cancel};k[this.selection]=this.bound.eventStop;this.document.addEvents(k)},check:function(d){if(this.options.preventDefault){d.preventDefault()}var c=Math.round(Math.sqrt(Math.pow(d.page.x-this.mouse.start.x,2)+Math.pow(d.page.y-this.mouse.start.y,2)));if(c>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop});this.fireEvent("start",[this.element,d]).fireEvent("snap",this.element)}},drag:function(d){var e=this.options;if(e.preventDefault){d.preventDefault()}this.mouse.now=d.page;for(var f in e.modifiers){if(!e.modifiers[f]){continue}this.value.now[f]=this.mouse.now[f]-this.mouse.pos[f];if(e.invert){this.value.now[f]*=-1}if(e.limit&&this.limit[f]){if((this.limit[f][1]||this.limit[f][1]===0)&&(this.value.now[f]>this.limit[f][1])){this.value.now[f]=this.limit[f][1]}else{if((this.limit[f][0]||this.limit[f][0]===0)&&(this.value.now[f]<this.limit[f][0])){this.value.now[f]=this.limit[f][0]}}}if(e.grid[f]){this.value.now[f]-=((this.value.now[f]-(this.limit[f][0]||0))%e.grid[f])}if(e.style){this.element.setStyle(e.modifiers[f],this.value.now[f]+e.unit)}else{this.element[e.modifiers[f]]=this.value.now[f]}}this.fireEvent("drag",[this.element,d])},cancel:function(b){this.document.removeEvents({mousemove:this.bound.check,mouseup:this.bound.cancel});if(b){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element)}},stop:function(c){var d={mousemove:this.bound.drag,mouseup:this.bound.stop};d[this.selection]=this.bound.eventStop;this.document.removeEvents(d);if(c){this.fireEvent("complete",[this.element,c])}}});Element.implement({makeResizable:function(d){var c=new Drag(this,Object.merge({modifiers:{x:"width",y:"height"}},d));this.store("resizer",c);return c.addEvent("drag",function(){this.fireEvent("resize",c)}.bind(this))}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false,precalculate:false,includeMargins:true,checkDroppables:true},initialize:function(e,f){this.parent(e,f);e=this.element;this.droppables=$$(this.options.droppables);this.setContainer(this.options.container);if(this.options.style){if(this.options.modifiers.x=="left"&&this.options.modifiers.y=="top"){var h=e.getOffsetParent(),g=e.getStyles("left","top");if(h&&(g.left=="auto"||g.top=="auto")){e.setPosition(e.getPosition(h))}}if(e.getStyle("position")=="static"){e.setStyle("position","absolute")}}this.addEvent("start",this.checkDroppables,true);this.overed=null},setContainer:function(b){this.container=document.id(b);if(this.container&&typeOf(this.container)!="element"){this.container=document.id(this.container.getDocument().body)}},start:function(b){if(this.container){this.options.limit=this.calculateLimit()}if(this.options.precalculate){this.positions=this.droppables.map(function(a){return a.getCoordinates()})}this.parent(b)},calculateLimit:function(){var w=this.element,B=this.container,C=document.id(w.getOffsetParent())||document.body,y=B.getCoordinates(C),D={},E={},v={},z={},t={};["top","right","bottom","left"].each(function(a){D[a]=w.getStyle("margin-"+a).toInt();E[a]=w.getStyle("border-"+a).toInt();v[a]=B.getStyle("margin-"+a).toInt();z[a]=B.getStyle("border-"+a).toInt();t[a]=C.getStyle("padding-"+a).toInt()},this);var A=w.offsetWidth+D.left+D.right,q=w.offsetHeight+D.top+D.bottom,x=0,u=0,r=y.right-z.right-A,F=y.bottom-z.bottom-q;if(this.options.includeMargins){x+=D.left;u+=D.top}else{r+=D.right;F+=D.bottom}if(w.getStyle("position")=="relative"){var s=w.getCoordinates(C);s.left-=w.getStyle("left").toInt();s.top-=w.getStyle("top").toInt();x-=s.left;u-=s.top;if(B.getStyle("position")!="relative"){x+=z.left;u+=z.top}r+=D.left-s.left;F+=D.top-s.top;if(B!=C){x+=v.left+t.left;if(!t.left&&x<0){x=0}u+=C==document.body?0:v.top+t.top;if(!t.top&&u<0){u=0}}}else{x-=D.left;u-=D.top;if(B!=C){x+=y.left+z.left;u+=y.top+z.top}}return{x:[x,r],y:[u,F]}},getDroppableCoordinates:function(f){var d=f.getCoordinates();if(f.getStyle("position")=="fixed"){var e=window.getScroll();d.left+=e.x;d.right+=e.x;d.top+=e.y;d.bottom+=e.y}return d},checkDroppables:function(){var b=this.droppables.filter(function(e,f){e=this.positions?this.positions[f]:this.getDroppableCoordinates(e);var a=this.mouse.now;return(a.x>e.left&&a.x<e.right&&a.y<e.bottom&&a.y>e.top)},this).getLast();if(this.overed!=b){if(this.overed){this.fireEvent("leave",[this.element,this.overed])}if(b){this.fireEvent("enter",[this.element,b])}this.overed=b}},drag:function(b){this.parent(b);if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables()}},stop:function(b){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,b]);this.overed=null;return this.parent(b)}});Element.implement({makeDraggable:function(d){var c=new Drag.Move(this,d);this.store("dragger",c);return c}});var Slider=new Class({Implements:[Events,Options],Binds:["clickedElement","draggedKnob","scrolledElement"],options:{onTick:function(b){this.setKnobPosition(b)},initialStep:0,snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal"},initialize:function(i,h,j){this.setOptions(j);j=this.options;this.element=document.id(i);h=this.knob=document.id(h);this.previousChange=this.previousEnd=this.step=j.initialStep?j.initialStep:j.range?j.range[0]:0;var g={},k={x:false,y:false};switch(j.mode){case"vertical":this.axis="y";this.property="top";this.offset="offsetHeight";break;case"horizontal":this.axis="x";this.property="left";this.offset="offsetWidth"}this.setSliderDimensions();this.setRange(j.range,null,true);if(h.getStyle("position")=="static"){h.setStyle("position","relative")}h.setStyle(this.property,-j.offset);k[this.axis]=this.property;g[this.axis]=[-j.offset,this.full-j.offset];var l={snap:0,limit:g,modifiers:k,onDrag:this.draggedKnob,onStart:this.draggedKnob,onBeforeStart:(function(){this.isDragging=true}).bind(this),onCancel:function(){this.isDragging=false}.bind(this),onComplete:function(){this.isDragging=false;this.draggedKnob();this.end()}.bind(this)};if(j.snap){this.setSnap(l)}this.drag=new Drag(h,l);if(j.initialStep!=null){this.set(j.initialStep,true)}this.attach()},attach:function(){this.element.addEvent("mousedown",this.clickedElement);if(this.options.wheel){this.element.addEvent("mousewheel",this.scrolledElement)}this.drag.attach();return this},detach:function(){this.element.removeEvent("mousedown",this.clickedElement).removeEvent("mousewheel",this.scrolledElement);this.drag.detach();return this},autosize:function(){this.setSliderDimensions().setKnobPosition(this.toPosition(this.step));this.drag.options.limit[this.axis]=[-this.options.offset,this.full-this.options.offset];if(this.options.snap){this.setSnap()}return this},setSnap:function(b){if(!b){b=this.drag.options}b.grid=Math.ceil(this.stepWidth);b.limit[this.axis][1]=this.element[this.offset];return this},setKnobPosition:function(b){if(this.options.snap){b=this.toPosition(this.step)}this.knob.setStyle(this.property,b);return this},setSliderDimensions:function(){this.full=this.element.measure(function(){this.half=this.knob[this.offset]/2;return this.element[this.offset]-this.knob[this.offset]+(this.options.offset*2)}.bind(this));return this},set:function(d,c){if(!((this.range>0)^(d<this.min))){d=this.min}if(!((this.range>0)^(d>this.max))){d=this.max}this.step=(d).round(this.modulus.decimalLength);if(c){this.checkStep().setKnobPosition(this.toPosition(this.step))}else{this.checkStep().fireEvent("tick",this.toPosition(this.step)).fireEvent("move").end()}return this},setRange:function(e,g,h){this.min=Array.pick([e[0],0]);this.max=Array.pick([e[1],this.options.steps]);this.range=this.max-this.min;this.steps=this.options.steps||this.full;var f=this.stepSize=Math.abs(this.range)/this.steps;this.stepWidth=this.stepSize*this.full/Math.abs(this.range);this.setModulus();if(e){this.set(Array.pick([g,this.step]).limit(this.min,this.max),h)}return this},setModulus:function(){var d=((this.stepSize+"").split(".")[1]||[]).length,c=1+"";while(d--){c+="0"}this.modulus={multiplier:(c).toInt(10),decimalLength:c.length-1}},clickedElement:function(f){if(this.isDragging||f.target==this.knob){return}var d=this.range<0?-1:1,e=f.page[this.axis]-this.element.getPosition()[this.axis]-this.half;e=e.limit(-this.options.offset,this.full-this.options.offset);this.step=(this.min+d*this.toStep(e)).round(this.modulus.decimalLength);this.checkStep().fireEvent("tick",e).fireEvent("move").end()},scrolledElement:function(d){var c=(this.options.mode=="horizontal")?(d.wheel<0):(d.wheel>0);this.set(this.step+(c?-1:1)*this.stepSize);d.stop()},draggedKnob:function(){var c=this.range<0?-1:1,d=this.drag.value.now[this.axis];d=d.limit(-this.options.offset,this.full-this.options.offset);this.step=(this.min+c*this.toStep(d)).round(this.modulus.decimalLength);this.checkStep();this.fireEvent("move")},checkStep:function(){var b=this.step;if(this.previousChange!=b){this.previousChange=b;this.fireEvent("change",b)}return this},end:function(){var b=this.step;if(this.previousEnd!==b){this.previousEnd=b;this.fireEvent("complete",b+"")}return this},toStep:function(d){var c=(d+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?(c-(c*this.modulus.multiplier)%(this.stepSize*this.modulus.multiplier)/this.modulus.multiplier).round(this.modulus.decimalLength):c},toPosition:function(b){return(this.full*Math.abs(this.min-b))/(this.steps*this.stepSize)-this.options.offset||0}});var Sortables=new Class({Implements:[Events,Options],options:{opacity:1,clone:false,revert:false,handle:false,dragOptions:{},unDraggableTags:["button","input","a","textarea","select","option"]},initialize:function(d,c){this.setOptions(c);this.elements=[];this.lists=[];this.idle=true;this.addLists($$(document.id(d)||d));if(!this.options.clone){this.options.revert=false}if(this.options.revert){this.effect=new Fx.Morph(null,Object.merge({duration:250,link:"cancel"},this.options.revert))}},attach:function(){this.addLists(this.lists);return this},detach:function(){this.lists=this.removeLists(this.lists);return this},addItems:function(){Array.flatten(arguments).each(function(d){this.elements.push(d);var c=d.retrieve("sortables:start",function(a){this.start.call(this,a,d)}.bind(this));(this.options.handle?d.getElement(this.options.handle)||d:d).addEvent("mousedown",c)},this);return this},addLists:function(){Array.flatten(arguments).each(function(b){this.lists.include(b);this.addItems(b.getChildren())},this);return this},removeItems:function(){return $$(Array.flatten(arguments).map(function(d){this.elements.erase(d);var c=d.retrieve("sortables:start");(this.options.handle?d.getElement(this.options.handle)||d:d).removeEvent("mousedown",c);return d},this))},removeLists:function(){return $$(Array.flatten(arguments).map(function(b){this.lists.erase(b);this.removeItems(b.getChildren());return b},this))},getDroppableCoordinates:function(h){var g=h.getOffsetParent();var e=h.getPosition(g);var f={w:window.getScroll(),offsetParent:g.getScroll()};e.x+=f.offsetParent.x;e.y+=f.offsetParent.y;if(g.getStyle("position")=="fixed"){e.x-=f.w.x;e.y-=f.w.y}return e},getClone:function(d,e){if(!this.options.clone){return new Element(e.tagName).inject(document.body)}if(typeOf(this.options.clone)=="function"){return this.options.clone.call(this,d,e,this.list)}var f=e.clone(true).setStyles({margin:0,position:"absolute",visibility:"hidden",width:e.getStyle("width")}).addEvent("mousedown",function(a){e.fireEvent("mousedown",a)});if(f.get("html").test("radio")){f.getElements("input[type=radio]").each(function(b,a){b.set("name","clone_"+a);if(b.get("checked")){e.getElements("input[type=radio]")[a].set("checked",true)}})}return f.inject(this.list).setPosition(this.getDroppableCoordinates(this.element))},getDroppables:function(){var b=this.list.getChildren().erase(this.clone).erase(this.element);if(!this.options.constrain){b.append(this.lists).erase(this.list)}return b},insert:function(f,d){var e="inside";if(this.lists.contains(d)){this.list=d;this.drag.droppables=this.getDroppables()}else{e=this.element.getAllPrevious().contains(d)?"before":"after"}this.element.inject(d,e);this.fireEvent("sort",[this.element,this.clone])},start:function(c,d){if(!this.idle||c.rightClick||(!this.options.handle&&this.options.unDraggableTags.contains(c.target.get("tag")))){return}this.idle=false;this.element=d;this.opacity=d.getStyle("opacity");this.list=d.getParent();this.clone=this.getClone(c,d);this.drag=new Drag.Move(this.clone,Object.merge({droppables:this.getDroppables()},this.options.dragOptions)).addEvents({onSnap:function(){c.stop();this.clone.setStyle("visibility","visible");this.element.setStyle("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone])}.bind(this),onEnter:this.insert.bind(this),onCancel:this.end.bind(this),onComplete:this.end.bind(this)});this.clone.inject(this.element,"before");this.drag.start(c)},end:function(){this.drag.detach();this.element.setStyle("opacity",this.opacity);var g=this;if(this.effect){var j=this.element.getStyles("width","height"),h=this.clone,i=h.computePosition(this.getDroppableCoordinates(h));var f=function(){this.removeEvent("cancel",f);h.destroy();g.reset()};this.effect.element=h;this.effect.start({top:i.top,left:i.left,width:j.width,height:j.height,opacity:0.25}).addEvent("cancel",f).chain(f)}else{this.clone.destroy();g.reset()}},reset:function(){this.idle=true;this.fireEvent("complete",this.element)},serialize:function(){var f=Array.link(arguments,{modifier:Type.isFunction,index:function(a){return a!=null}});var d=this.lists.map(function(a){return a.getChildren().map(f.modifier||function(b){return b.get("id")},this)},this);var e=f.index;if(this.lists.length==1){e=0}return(e||e===0)&&e>=0&&e<this.lists.length?d[e]:d}});Request.JSONP=new Class({Implements:[Chain,Events,Options],options:{onRequest:function(b){if(this.options.log&&window.console&&console.log){console.log("JSONP retrieving script with url:"+b)}},onError:function(b){if(this.options.log&&window.console&&console.warn){console.warn("JSONP "+b+" will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs")}},url:"",callbackKey:"callback",injectScript:document.head,data:"",link:"ignore",timeout:0,log:false},initialize:function(b){this.setOptions(b)},send:function(l){if(!Request.prototype.check.call(this,l)){return this}this.running=true;var k=typeOf(l);if(k=="string"||k=="element"){l={data:l}}l=Object.merge(this.options,l||{});var j=l.data;switch(typeOf(j)){case"element":j=document.id(j).toQueryString();break;case"object":case"hash":j=Object.toQueryString(j)}var g=this.index=Request.JSONP.counter++;var i=l.url+(l.url.test("\\?")?"&":"?")+(l.callbackKey)+"=Request.JSONP.request_map.request_"+g+(j?"&"+j:"");if(i.length>2083){this.fireEvent("error",i)}Request.JSONP.request_map["request_"+g]=function(){this.success(arguments,g)}.bind(this);var h=this.getScript(i).inject(l.injectScript);this.fireEvent("request",[i,h]);if(l.timeout){this.timeout.delay(l.timeout,this)}return this},getScript:function(b){if(!this.script){this.script=new Element("script",{type:"text/javascript",async:true,src:b})}return this.script},success:function(c,d){if(!this.running){return}this.clear().fireEvent("complete",c).fireEvent("success",c).callChain()},cancel:function(){if(this.running){this.clear().fireEvent("cancel")}return this},isRunning:function(){return !!this.running},clear:function(){this.running=false;if(this.script){this.script.destroy();this.script=null}return this},timeout:function(){if(this.running){this.running=false;this.fireEvent("timeout",[this.script.get("src"),this.script]).fireEvent("failure").cancel()}return this}});Request.JSONP.counter=0;Request.JSONP.request_map={};Request.Queue=new Class({Implements:[Options,Events],Binds:["attach","request","complete","cancel","success","failure","exception"],options:{stopOnFailure:true,autoAdvance:true,concurrent:1,requests:{}},initialize:function(d){var c;if(d){c=d.requests;delete d.requests}this.setOptions(d);this.requests={};this.queue=[];this.reqBinders={};if(c){this.addRequests(c)}},addRequest:function(d,c){this.requests[d]=c;this.attach(d,c);return this},addRequests:function(b){Object.each(b,function(d,a){this.addRequest(a,d)},this);return this},getName:function(b){return Object.keyOf(this.requests,b)},attach:function(d,c){if(c._groupSend){return this}["request","complete","cancel","success","failure","exception"].each(function(a){if(!this.reqBinders[d]){this.reqBinders[d]={}}this.reqBinders[d][a]=function(){this["on"+a.capitalize()].apply(this,[d,c].append(arguments))}.bind(this);c.addEvent(a,this.reqBinders[d][a])},this);c._groupSend=c.send;c.send=function(a){this.send(d,a);return c}.bind(this);return this},removeRequest:function(c){var d=typeOf(c)=="object"?this.getName(c):c;if(!d&&typeOf(d)!="string"){return this}c=this.requests[d];if(!c){return this}["request","complete","cancel","success","failure","exception"].each(function(a){c.removeEvent(a,this.reqBinders[d][a])},this);c.send=c._groupSend;delete c._groupSend;return this},getRunning:function(){return Object.filter(this.requests,function(b){return b.running})},isRunning:function(){return !!(Object.keys(this.getRunning()).length)},send:function(d,e){var f=function(){this.requests[d]._groupSend(e);this.queue.erase(f)}.bind(this);f.name=d;if(Object.keys(this.getRunning()).length>=this.options.concurrent||(this.error&&this.options.stopOnFailure)){this.queue.push(f)}else{f()}return this},hasNext:function(b){return(!b)?!!this.queue.length:!!this.queue.filter(function(a){return a.name==b}).length},resume:function(){this.error=false;(this.options.concurrent-Object.keys(this.getRunning()).length).times(this.runNext,this);return this},runNext:function(d){if(!this.queue.length){return this}if(!d){this.queue[0]()}else{var c;this.queue.each(function(a){if(!c&&a.name==d){c=true;a()}})}return this},runAll:function(){this.queue.each(function(b){b()});return this},clear:function(b){if(!b){this.queue.empty()}else{this.queue=this.queue.map(function(a){if(a.name!=b){return a}else{return false}}).filter(function(a){return a})}return this},cancel:function(b){this.requests[b].cancel();return this},onRequest:function(){this.fireEvent("request",arguments)},onComplete:function(){this.fireEvent("complete",arguments);if(!this.queue.length){this.fireEvent("end")}},onCancel:function(){if(this.options.autoAdvance&&!this.error){this.runNext()}this.fireEvent("cancel",arguments)},onSuccess:function(){if(this.options.autoAdvance&&!this.error){this.runNext()}this.fireEvent("success",arguments)},onFailure:function(){this.error=true;if(!this.options.stopOnFailure&&this.options.autoAdvance){this.runNext()}this.fireEvent("failure",arguments)},onException:function(){this.error=true;if(!this.options.stopOnFailure&&this.options.autoAdvance){this.runNext()}this.fireEvent("exception",arguments)}});Request.implement({options:{initialDelay:5000,delay:5000,limit:60000},startTimer:function(c){var d=function(){if(!this.running){this.send({data:c})}};this.lastDelay=this.options.initialDelay;this.timer=d.delay(this.lastDelay,this);this.completeCheck=function(a){clearTimeout(this.timer);this.lastDelay=(a)?this.options.delay:(this.lastDelay+this.options.delay).min(this.options.limit);this.timer=d.delay(this.lastDelay,this)};return this.addEvent("complete",this.completeCheck)},stopTimer:function(){clearTimeout(this.timer);return this.removeEvent("complete",this.completeCheck)}});var Asset={javascript:function(i,f){if(!f){f={}}var g=new Element("script",{src:i,type:"text/javascript"}),h=f.document||document,j=f.onload||f.onLoad;delete f.onload;delete f.onLoad;delete f.document;if(j){if(!g.addEventListener){g.addEvent("readystatechange",function(){if(["loaded","complete"].contains(this.readyState)){j.call(this)}})}else{g.addEvent("load",j)}}return g.set(f).inject(h.head)},css:function(i,g){if(!g){g={}}var f=new Element("link",{rel:"stylesheet",media:"screen",type:"text/css",href:i});var j=g.onload||g.onLoad,h=g.document||document;delete g.onload;delete g.onLoad;delete g.document;if(j){f.addEvent("load",j)}return f.set(g).inject(h.head)},image:function(h,e){if(!e){e={}}var g=new Image(),f=document.id(g)||new Element("img");["load","abort","error"].each(function(d){var b="on"+d,c="on"+d.capitalize(),a=e[b]||e[c]||function(){};delete e[c];delete e[b];g[b]=function(){if(!g){return}if(!f.parentNode){f.width=g.width;f.height=g.height}g=g.onload=g.onabort=g.onerror=null;a.delay(1,f,f);f.fireEvent(d,f,1)}});g.src=f.src=h;if(g&&g.complete){g.onload.delay(1)}return f.set(e)},images:function(h,e){h=Array.from(h);var g=function(){},f=0;e=Object.merge({onComplete:g,onProgress:g,onError:g,properties:{}},e);return new Elements(h.map(function(a,b){return Asset.image(a,Object.append(e.properties,{onload:function(){f++;e.onProgress.call(this,f,b,a);if(f==h.length){e.onComplete()}},onerror:function(){f++;e.onError.call(this,f,b,a);if(f==h.length){e.onComplete()}}}))}))}};(function(){var b=this.Color=new Type("Color",function(f,e){if(arguments.length>=3){e="rgb";f=Array.slice(arguments,0,3)}else{if(typeof f=="string"){if(f.match(/rgb/)){f=f.rgbToHex().hexToRgb(true)}else{if(f.match(/hsb/)){f=f.hsbToRgb()}else{f=f.hexToRgb(true)}}}}e=e||"rgb";switch(e){case"hsb":var a=f;f=f.hsbToRgb();f.hsb=a;break;case"hex":f=f.hexToRgb(true);break}f.rgb=f.slice(0,3);f.hsb=f.hsb||f.rgbToHsb();f.hex=f.rgbToHex();return Object.append(f,this)});b.implement({mix:function(){var a=Array.slice(arguments);var e=(typeOf(a.getLast())=="number")?a.pop():50;var f=this.slice();a.each(function(d){d=new b(d);for(var c=0;c<3;c++){f[c]=Math.round((f[c]/100*(100-e))+(d[c]/100*e))}});return new b(f,"rgb")},invert:function(){return new b(this.map(function(a){return 255-a}))},setHue:function(a){return new b([a,this.hsb[1],this.hsb[2]],"hsb")},setSaturation:function(a){return new b([this.hsb[0],a,this.hsb[2]],"hsb")},setBrightness:function(a){return new b([this.hsb[0],this.hsb[1],a],"hsb")}});this.$RGB=function(a,f,g){return new b([a,f,g],"rgb")};this.$HSB=function(a,f,g){return new b([a,f,g],"hsb")};this.$HEX=function(a){return new b(a,"hex")};Array.implement({rgbToHsb:function(){var w=this[0],v=this[1],o=this[2],r=0;var p=Math.max(w,v,o),t=Math.min(w,v,o);var n=p-t;var q=p/255,s=(p!=0)?n/p:0;if(s!=0){var u=(p-w)/n;var x=(p-v)/n;var a=(p-o)/n;if(w==p){r=a-x}else{if(v==p){r=2+u-a}else{r=4+x-u}}r/=6;if(r<0){r++}}return[Math.round(r*360),Math.round(s*100),Math.round(q*100)]},hsbToRgb:function(){var k=Math.round(this[2]/100*255);if(this[1]==0){return[k,k,k]}else{var a=this[0]%360;var i=a%60;var f=Math.round((this[2]*(100-this[1]))/10000*255);var j=Math.round((this[2]*(6000-this[1]*i))/600000*255);var l=Math.round((this[2]*(6000-this[1]*(60-i)))/600000*255);switch(Math.floor(a/60)){case 0:return[k,l,f];case 1:return[j,k,f];case 2:return[f,k,l];case 3:return[f,j,k];case 4:return[l,f,k];case 5:return[k,f,j]}}return false}});String.implement({rgbToHsb:function(){var a=this.match(/\d{1,3}/g);return(a)?a.rgbToHsb():null},hsbToRgb:function(){var a=this.match(/\d{1,3}/g);return(a)?a.hsbToRgb():null}})})();(function(){this.Group=new Class({initialize:function(){this.instances=Array.flatten(arguments)},addEvent:function(l,m){var j=this.instances,i=j.length,k=i,n=new Array(i),h=this;j.each(function(b,a){b.addEvent(l,function(){if(!n[a]){k--}n[a]=arguments;if(!k){m.call(h,j,b,n);k=i;n=new Array(i)}})})}})})();Hash.Cookie=new Class({Extends:Cookie,options:{autoSave:true},initialize:function(c,d){this.parent(c,d);this.load()},save:function(){var b=JSON.encode(this.hash);if(!b||b.length>4096){return false}if(b=="{}"){this.dispose()}else{this.write(b)}return true},load:function(){this.hash=new Hash(JSON.decode(this.read(),true));return this}});Hash.each(Hash.prototype,function(c,d){if(typeof c=="function"){Hash.Cookie.implement(d,function(){var a=c.apply(this.hash,arguments);if(this.options.autoSave){this.save()}return a})}});(function(){var b=this.Table=function(){this.length=0;var d=[],a=[];this.set=function(i,c){var j=d.indexOf(i);if(j==-1){var h=d.length;d[h]=i;a[h]=c;this.length++}else{a[j]=c}return this};this.get=function(c){var f=d.indexOf(c);return(f==-1)?null:a[f]};this.erase=function(c){var f=d.indexOf(c);if(f!=-1){this.length--;d.splice(f,1);return a.splice(f,1)[0]}return null};this.each=this.forEach=function(h,c){for(var i=0,j=this.length;i<j;i++){h.call(c,d[i],a[i],this)}}};if(this.Type){new Type("Table",b)}})();(function(){var Swiff=this.Swiff=new Class({Implements:Options,options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"window",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object},initialize:function(path,options){this.instance="Swiff_"+String.uniqueID();this.setOptions(options);options=this.options;var id=this.id=options.id||this.instance;var container=document.id(options.container);Swiff.CallBacks[this.instance]={};var params=options.params,vars=options.vars,callBacks=options.callBacks;var properties=Object.append({height:options.height,width:options.width},options.properties);var self=this;for(var callBack in callBacks){Swiff.CallBacks[this.instance][callBack]=(function(option){return function(){return option.apply(self.object,arguments)}})(callBacks[callBack]);vars[callBack]="Swiff.CallBacks."+this.instance+"."+callBack}params.flashVars=Object.toQueryString(vars);if("ActiveXObject" in window){properties.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";params.movie=path}else{properties.type="application/x-shockwave-flash"}properties.data=path;var build='<object id="'+id+'"';for(var property in properties){build+=" "+property+'="'+properties[property]+'"'}build+=">";for(var param in params){if(params[param]){build+='<param name="'+param+'" value="'+params[param]+'" />'}}build+="</object>";this.object=((container)?container.empty():new Element("div")).set("html",build).firstChild},replaces:function(element){element=document.id(element,true);element.parentNode.replaceChild(this.toElement(),element);return this},inject:function(element){document.id(element,true).appendChild(this.toElement());return this},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].append(arguments))}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");return eval(rs)}})();var HtmlTable=new Class({Implements:[Options,Events,Class.Occlude],options:{properties:{cellpadding:0,cellspacing:0,border:0},rows:[],headers:[],footers:[]},property:"HtmlTable",initialize:function(){var b=Array.link(arguments,{options:Type.isObject,table:Type.isElement,id:Type.isString});this.setOptions(b.options);if(!b.table&&b.id){b.table=document.id(b.id)}this.element=b.table||new Element("table",this.options.properties);if(this.occlude()){return this.occluded}this.build()},build:function(){this.element.store("HtmlTable",this);this.body=document.id(this.element.tBodies[0])||new Element("tbody").inject(this.element);$$(this.body.rows);if(this.options.headers.length){this.setHeaders(this.options.headers)}else{this.thead=document.id(this.element.tHead)}if(this.thead){this.head=this.getHead()}if(this.options.footers.length){this.setFooters(this.options.footers)}this.tfoot=document.id(this.element.tFoot);if(this.tfoot){this.foot=document.id(this.tfoot.rows[0])}this.options.rows.each(function(b){this.push(b)},this)},toElement:function(){return this.element},empty:function(){this.body.empty();return this},set:function(h,g){var i=(h=="headers")?"tHead":"tFoot",f=i.toLowerCase();this[f]=(document.id(this.element[i])||new Element(f).inject(this.element,"top")).empty();var j=this.push(g,{},this[f],h=="headers"?"th":"td");if(h=="headers"){this.head=this.getHead()}else{this.foot=this.getHead()}return j},getHead:function(){var b=this.thead.rows;return b.length>1?$$(b):b.length?document.id(b[0]):false},setHeaders:function(b){this.set("headers",b);return this},setFooters:function(b){this.set("footers",b);return this},update:function(i,h,g){var f=i.getChildren(g||"td"),j=f.length-1;h.each(function(b,e){var a=f[e]||new Element(g||"td").inject(i),c=((b&&Object.prototype.hasOwnProperty.call(b,"content"))?b.content:"")||b,d=typeOf(c);if(b&&Object.prototype.hasOwnProperty.call(b,"properties")){a.set(b.properties)}if(/(element(s?)|array|collection)/.test(d)){a.empty().adopt(c)}else{a.set("html",c)}if(e>j){f.push(a)}else{f[e]=a}});return{tr:i,tds:f}},push:function(h,j,i,g,f){if(typeOf(h)=="element"&&h.get("tag")=="tr"){h.inject(i||this.body,f);return{tr:h,tds:h.getChildren("td")}}return this.update(new Element("tr",j).inject(i||this.body,f),h,g)},pushMany:function(i,j,h,g,f){return i.map(function(a){return this.push(a,j,h,g,f)},this)}});["adopt","inject","wraps","grab","replaces","dispose"].each(function(b){HtmlTable.implement(b,function(){this.element[b].apply(this.element,arguments);return this})});HtmlTable=Class.refactor(HtmlTable,{options:{classZebra:"table-tr-odd",zebra:true,zebraOnlyVisibleRows:true},initialize:function(){this.previous.apply(this,arguments);if(this.occluded){return this.occluded}if(this.options.zebra){this.updateZebras()}},updateZebras:function(){var b=0;Array.each(this.body.rows,function(a){if(!this.options.zebraOnlyVisibleRows||a.isDisplayed()){this.zebra(a,b++)}},this)},setRowStyle:function(c,d){if(this.previous){this.previous(c,d)}this.zebra(c,d)},zebra:function(c,d){return c[((d%2)?"remove":"add")+"Class"](this.options.classZebra)},push:function(){var b=this.previous.apply(this,arguments);if(this.options.zebra){this.updateZebras()}return b}});(function(){var d=document.createElement("table");try{d.innerHTML="<tr><td></td></tr>";d=d.childNodes.length===0}catch(c){d=true}HtmlTable=Class.refactor(HtmlTable,{options:{sortIndex:0,sortReverse:false,parsers:[],defaultParser:"string",classSortable:"table-sortable",classHeadSort:"table-th-sort",classHeadSortRev:"table-th-sort-rev",classNoSort:"table-th-nosort",classGroupHead:"table-tr-group-head",classGroup:"table-tr-group",classCellSort:"table-td-sort",classSortSpan:"table-th-sort-span",sortable:false,thSelector:"th"},initialize:function(){this.previous.apply(this,arguments);if(this.occluded){return this.occluded}this.sorted={index:null,dir:1};if(!this.bound){this.bound={}}this.bound.headClick=this.headClick.bind(this);this.sortSpans=new Elements();if(this.options.sortable){this.enableSort();if(this.options.sortIndex!=null){this.sort(this.options.sortIndex,this.options.sortReverse)}}},attachSorts:function(a){this.detachSorts();if(a!==false){this.element.addEvent("click:relay("+this.options.thSelector+")",this.bound.headClick)}},detachSorts:function(){this.element.removeEvents("click:relay("+this.options.thSelector+")")},setHeaders:function(){this.previous.apply(this,arguments);if(this.sortable){this.setParsers()}},setParsers:function(){this.parsers=this.detectParsers()},detectParsers:function(){return this.head&&this.head.getElements(this.options.thSelector).flatten().map(this.detectParser,this)},detectParser:function(n,m){if(n.hasClass(this.options.classNoSort)||n.retrieve("htmltable-parser")){return n.retrieve("htmltable-parser")}var l=new Element("div");l.adopt(n.childNodes).inject(n);var b=new Element("span",{"class":this.options.classSortSpan}).inject(l,"top");this.sortSpans.push(b);var a=this.options.parsers[m],j=this.body.rows,k;switch(typeOf(a)){case"function":a={convert:a};k=true;break;case"string":a=a;k=true;break}if(!k){HtmlTable.ParserPriority.some(function(f){var i=HtmlTable.Parsers[f],s=i.match;if(!s){return false}for(var r=0,e=j.length;r<e;r++){var g=document.id(j[r].cells[m]),h=g?g.get("html").clean():"";if(h&&s.test(h)){a=i;return true}}})}if(!a){a=this.options.defaultParser}n.store("htmltable-parser",a);return a},headClick:function(a,b){if(!this.head||b.hasClass(this.options.classNoSort)){return}return this.sort(Array.indexOf(this.head.getElements(this.options.thSelector).flatten(),b)%this.body.rows[0].cells.length)},serialize:function(){var a=this.previous.apply(this,arguments)||{};if(this.options.sortable){a.sortIndex=this.sorted.index;a.sortReverse=this.sorted.reverse}return a},restore:function(a){if(this.options.sortable&&a.sortIndex){this.sort(a.sortIndex,a.sortReverse)}this.previous.apply(this,arguments)},setSortedState:function(a,b){if(b!=null){this.sorted.reverse=b}else{if(this.sorted.index==a){this.sorted.reverse=!this.sorted.reverse}else{this.sorted.reverse=this.sorted.index==null}}if(a!=null){this.sorted.index=a}},setHeadSort:function(b){var a=$$(!this.head.length?this.head.cells[this.sorted.index]:this.head.map(function(f){return f.getElements(this.options.thSelector)[this.sorted.index]},this).clean());if(!a.length){return}if(b){a.addClass(this.options.classHeadSort);if(this.sorted.reverse){a.addClass(this.options.classHeadSortRev)}else{a.removeClass(this.options.classHeadSortRev)}}else{a.removeClass(this.options.classHeadSort).removeClass(this.options.classHeadSortRev)}},setRowSort:function(q,r){var n=q.length,o=this.body,l,m;while(n){var b=q[--n],p=b.position,a=o.rows[p];if(a.disabled){continue}if(!r){l=this.setGroupSort(l,a,b);this.setRowStyle(a,n)}o.appendChild(a);for(m=0;m<n;m++){if(q[m].position>p){q[m].position--}}}},setRowStyle:function(a,b){this.previous(a,b);a.cells[this.sorted.index].addClass(this.options.classCellSort)},setGroupSort:function(b,a,f){if(b==f.value){a.removeClass(this.options.classGroupHead).addClass(this.options.classGroup)}else{a.removeClass(this.options.classGroup).addClass(this.options.classGroupHead)}return f.value},getParser:function(){var a=this.parsers[this.sorted.index];return typeOf(a)=="string"?HtmlTable.Parsers[a]:a},sort:function(j,k,b){if(!this.head){return}if(!b){this.clearSort();this.setSortedState(j,k);this.setHeadSort(true)}var a=this.getParser();if(!a){return}var l;if(!d){l=this.body.getParent();this.body.dispose()}var i=this.parseData(a).sort(function(e,f){if(e.value===f.value){return 0}return e.value>f.value?1:-1});if(this.sorted.reverse==(a==HtmlTable.Parsers["input-checked"])){i.reverse(true)}this.setRowSort(i,b);if(l){l.grab(this.body)}this.fireEvent("stateChanged");return this.fireEvent("sort",[this.body,this.sorted.index])},parseData:function(a){return Array.map(this.body.rows,function(b,h){var g=a.convert.call(document.id(b.cells[this.sorted.index]));return{position:h,value:g}},this)},clearSort:function(){this.setHeadSort(false);this.body.getElements("td").removeClass(this.options.classCellSort)},reSort:function(){if(this.sortable){this.sort.call(this,this.sorted.index,this.sorted.reverse)}return this},enableSort:function(){this.element.addClass(this.options.classSortable);this.attachSorts(true);this.setParsers();this.sortable=true;return this},disableSort:function(){this.element.removeClass(this.options.classSortable);this.attachSorts(false);this.sortSpans.each(function(a){a.destroy()});this.sortSpans.empty();this.sortable=false;return this}});HtmlTable.ParserPriority=["date","input-checked","input-value","float","number"];HtmlTable.Parsers={date:{match:/^\d{2}[-\/ ]\d{2}[-\/ ]\d{2,4}$/,convert:function(){var a=Date.parse(this.get("text").stripTags());return(typeOf(a)=="date")?a.format("db"):""},type:"date"},"input-checked":{match:/ type="(radio|checkbox)" /,convert:function(){return this.getElement("input").checked}},"input-value":{match:/<input/,convert:function(){return this.getElement("input").value}},number:{match:/^\d+[^\d.,]*$/,convert:function(){return this.get("text").stripTags().toInt()},number:true},numberLax:{match:/^[^\d]+\d+$/,convert:function(){return this.get("text").replace(/[^-?^0-9]/,"").stripTags().toInt()},number:true},"float":{match:/^[\d]+\.[\d]+/,convert:function(){return this.get("text").replace(/[^-?^\d.]/,"").stripTags().toFloat()},number:true},floatLax:{match:/^[^\d]+[\d]+\.[\d]+$/,convert:function(){return this.get("text").replace(/[^-?^\d.]/,"").stripTags().toFloat()},number:true},string:{match:null,convert:function(){return this.get("text").stripTags().toLowerCase()}},title:{match:null,convert:function(){return this.title}}};HtmlTable.defineParsers=function(b){HtmlTable.Parsers=Object.append(HtmlTable.Parsers,b);for(var a in b){HtmlTable.ParserPriority.unshift(a)}}})();(function(){var g=this.Keyboard=new Class({Extends:Events,Implements:[Options],options:{defaultEventType:"keydown",active:false,manager:null,events:{},nonParsedEvents:["activate","deactivate","onactivate","ondeactivate","changed","onchanged"]},initialize:function(a){if(a&&a.manager){this._manager=a.manager;delete a.manager}this.setOptions(a);this._setup()},addEvent:function(a,b,c){return this.parent(g.parse(a,this.options.defaultEventType,this.options.nonParsedEvents),b,c)},removeEvent:function(a,b){return this.parent(g.parse(a,this.options.defaultEventType,this.options.nonParsedEvents),b)},toggleActive:function(){return this[this.isActive()?"deactivate":"activate"]()},activate:function(a){if(a){if(a.isActive()){return this}if(this._activeKB&&a!=this._activeKB){this.previous=this._activeKB;this.previous.fireEvent("deactivate")}this._activeKB=a.fireEvent("activate");g.manager.fireEvent("changed")}else{if(this._manager){this._manager.activate(this)}}return this},isActive:function(){return this._manager?(this._manager._activeKB==this):(g.manager==this)},deactivate:function(a){if(a){if(a===this._activeKB){this._activeKB=null;a.fireEvent("deactivate");g.manager.fireEvent("changed")}}else{if(this._manager){this._manager.deactivate(this)}}return this},relinquish:function(){if(this.isActive()&&this._manager&&this._manager.previous){this._manager.activate(this._manager.previous)}else{this.deactivate()}return this},manage:function(a){if(a._manager){a._manager.drop(a)}this._instances.push(a);a._manager=this;if(!this._activeKB){this.activate(a)}return this},drop:function(a){a.relinquish();this._instances.erase(a);if(this._activeKB==a){if(this.previous&&this._instances.contains(this.previous)){this.activate(this.previous)}else{this._activeKB=this._instances[0]}}return this},trace:function(){g.trace(this)},each:function(a){g.each(this,a)},_instances:[],_disable:function(a){if(this._activeKB==a){this._activeKB=null}},_setup:function(){this.addEvents(this.options.events);if(g.manager&&!this._manager){g.manager.manage(this)}if(this.options.active){this.activate()}else{this.relinquish()}},_handle:function(a,b){if(a.preventKeyboardPropagation){return}var c=!!this._manager;if(c&&this._activeKB){this._activeKB._handle(a,b);if(a.preventKeyboardPropagation){return}}this.fireEvent(b,a);if(!c&&this._activeKB){this._activeKB._handle(a,b)}}});var f={};var j=["shift","control","alt","meta"];var h=/^(?:shift|control|ctrl|alt|meta)$/;g.parse=function(d,e,a){if(a&&a.contains(d.toLowerCase())){return d}d=d.toLowerCase().replace(/^(keyup|keydown):/,function(k,n){e=n;return""});if(!f[d]){if(d!="+"){var l,b={};d.split("+").each(function(k){if(h.test(k)){b[k]=true}else{l=k}});b.control=b.control||b.ctrl;var c=[];j.each(function(k){if(b[k]){c.push(k)}});if(l){c.push(l)}f[d]=c.join("+")}else{f[d]=d}}return e+":keys("+f[d]+")"};g.each=function(c,b){var a=c||g.manager;while(a){b(a);a=a._activeKB}};g.stop=function(a){a.preventKeyboardPropagation=true};g.manager=new g({active:true});g.trace=function(b){b=b||g.manager;var a=window.console&&console.log;if(a){console.log("the following items have focus: ")}g.each(b,function(c){if(a){console.log(document.id(c.widget)||c.wiget||c)}})};var i=function(a){var b=[];j.each(function(c){if(a[c]){b.push(c)}});if(!h.test(a.key)){b.push(a.key)}g.manager._handle(a,a.type+":keys("+b.join("+")+")")};document.addEvents({keyup:i,keydown:i})})();Keyboard.prototype.options.nonParsedEvents.combine(["rebound","onrebound"]);Keyboard.implement({addShortcut:function(c,d){this._shortcuts=this._shortcuts||[];this._shortcutIndex=this._shortcutIndex||{};d.getKeyboard=Function.from(this);d.name=c;this._shortcutIndex[c]=d;this._shortcuts.push(d);if(d.keys){this.addEvent(d.keys,d.handler)}return this},addShortcuts:function(c){for(var d in c){this.addShortcut(d,c[d])}return this},removeShortcut:function(c){var d=this.getShortcut(c);if(d&&d.keys){this.removeEvent(d.keys,d.handler);delete this._shortcutIndex[c];this._shortcuts.erase(d)}return this},removeShortcuts:function(b){b.each(this.removeShortcut,this);return this},getShortcuts:function(){return this._shortcuts||[]},getShortcut:function(b){return(this._shortcutIndex||{})[b]}});Keyboard.rebind=function(c,d){Array.from(d).each(function(a){a.getKeyboard().removeEvent(a.keys,a.handler);a.getKeyboard().addEvent(c,a.handler);a.keys=c;a.getKeyboard().fireEvent("rebound")})};Keyboard.getActiveShortcuts=function(d){var e=[],f=[];Keyboard.each(d,[].push.bind(e));e.each(function(a){f.extend(a.getShortcuts())});return f};Keyboard.getShortcut=function(j,f,i){i=i||{};var g=i.many?[]:null,h=i.many?function(a){var b=a.getShortcut(j);if(b){g.push(b)}}:function(a){if(!g){g=a.getShortcut(j)}};Keyboard.each(f,h);return g};Keyboard.getShortcuts=function(c,d){return Keyboard.getShortcut(c,d,{many:true})};HtmlTable=Class.refactor(HtmlTable,{options:{useKeyboard:true,classRowSelected:"table-tr-selected",classRowHovered:"table-tr-hovered",classSelectable:"table-selectable",shiftForMultiSelect:true,allowMultiSelect:true,selectable:false,selectHiddenRows:false},initialize:function(){this.previous.apply(this,arguments);if(this.occluded){return this.occluded}this.selectedRows=new Elements();if(!this.bound){this.bound={}}this.bound.mouseleave=this.mouseleave.bind(this);this.bound.clickRow=this.clickRow.bind(this);this.bound.activateKeyboard=function(){if(this.keyboard&&this.selectEnabled){this.keyboard.activate()}}.bind(this);if(this.options.selectable){this.enableSelect()}},empty:function(){if(this.body.rows.length){this.selectNone()}return this.previous()},enableSelect:function(){this.selectEnabled=true;this.attachSelects();this.element.addClass(this.options.classSelectable);return this},disableSelect:function(){this.selectEnabled=false;this.attachSelects(false);this.element.removeClass(this.options.classSelectable);return this},push:function(){var b=this.previous.apply(this,arguments);this.updateSelects();return b},toggleRow:function(b){return this[(this.isSelected(b)?"de":"")+"selectRow"](b)},selectRow:function(c,d){if(this.isSelected(c)||(!d&&!this.body.getChildren().contains(c))){return}if(!this.options.allowMultiSelect){this.selectNone()}if(!this.isSelected(c)){this.selectedRows.push(c);c.addClass(this.options.classRowSelected);this.fireEvent("rowFocus",[c,this.selectedRows]);this.fireEvent("stateChanged")}this.focused=c;document.clearSelection();return this},isSelected:function(b){return this.selectedRows.contains(b)},getSelected:function(){return this.selectedRows},serialize:function(){var b=this.previous.apply(this,arguments)||{};if(this.options.selectable){b.selectedRows=this.selectedRows.map(function(a){return Array.indexOf(this.body.rows,a)}.bind(this))}return b},restore:function(b){if(this.options.selectable&&b.selectedRows){b.selectedRows.each(function(a){this.selectRow(this.body.rows[a])}.bind(this))}this.previous.apply(this,arguments)},deselectRow:function(c,d){if(!this.isSelected(c)||(!d&&!this.body.getChildren().contains(c))){return}this.selectedRows=new Elements(Array.from(this.selectedRows).erase(c));c.removeClass(this.options.classRowSelected);this.fireEvent("rowUnfocus",[c,this.selectedRows]);this.fireEvent("stateChanged");return this},selectAll:function(b){if(!b&&!this.options.allowMultiSelect){return}this.selectRange(0,this.body.rows.length,b);return this},selectNone:function(){return this.selectAll(true)},selectRange:function(h,i,k){if(!this.options.allowMultiSelect&&!k){return}var j=k?"deselectRow":"selectRow",l=Array.clone(this.body.rows);if(typeOf(h)=="element"){h=l.indexOf(h)}if(typeOf(i)=="element"){i=l.indexOf(i)}i=i<l.length-1?i:l.length-1;if(i<h){var m=h;h=i;i=m}for(var n=h;n<=i;n++){if(this.options.selectHiddenRows||l[n].isDisplayed()){this[j](l[n],true)}}return this},deselectRange:function(c,d){this.selectRange(c,d,true)},enterRow:function(b){if(this.hovered){this.hovered=this.leaveRow(this.hovered)}this.hovered=b.addClass(this.options.classRowHovered)},leaveRow:function(b){b.removeClass(this.options.classRowHovered)},updateSelects:function(){Array.each(this.body.rows,function(d){var c=d.retrieve("binders");if(!c&&!this.selectEnabled){return}if(!c){c={mouseenter:this.enterRow.pass([d],this),mouseleave:this.leaveRow.pass([d],this)};d.store("binders",c)}if(this.selectEnabled){d.addEvents(c)}else{d.removeEvents(c)}},this)},shiftFocus:function(d,e){if(!this.focused){return this.selectRow(this.body.rows[0],e)}var f=this.getRowByOffset(d,this.options.selectHiddenRows);if(f===null||this.focused==this.body.rows[f]){return this}this.toggleRow(this.body.rows[f],e)},clickRow:function(e,d){var f=(e.shift||e.meta||e.control)&&this.options.shiftForMultiSelect;if(!f&&!(e.rightClick&&this.isSelected(d)&&this.options.allowMultiSelect)){this.selectNone()}if(e.rightClick){this.selectRow(d)}else{this.toggleRow(d)}if(e.shift){this.selectRange(this.rangeStart||this.body.rows[0],d,this.rangeStart?!this.isSelected(d):true);this.focused=d}this.rangeStart=d},getRowByOffset:function(h,i){if(!this.focused){return 0}var f=Array.indexOf(this.body.rows,this.focused);if((f==0&&h<0)||(f==this.body.rows.length-1&&h>0)){return null}if(i){f+=h}else{var g=0,j=0;if(h>0){while(j<h&&f<this.body.rows.length-1){if(this.body.rows[++f].isDisplayed()){j++}}}else{while(j>h&&f>0){if(this.body.rows[--f].isDisplayed()){j--}}}}return f},attachSelects:function(m){m=m!=null?m:true;var j=m?"addEvents":"removeEvents";this.element[j]({mouseleave:this.bound.mouseleave,click:this.bound.activateKeyboard});this.body[j]({"click:relay(tr)":this.bound.clickRow,"contextmenu:relay(tr)":this.bound.clickRow});if(this.options.useKeyboard||this.keyboard){if(!this.keyboard){this.keyboard=new Keyboard()}if(!this.selectKeysDefined){this.selectKeysDefined=true;var k,l;var n=function(a){var b=function(d){clearTimeout(k);d.preventDefault();var c=this.body.rows[this.getRowByOffset(a,this.options.selectHiddenRows)];if(d.shift&&c&&this.isSelected(c)){this.deselectRow(this.focused);this.focused=c}else{if(c&&(!this.options.allowMultiSelect||!d.shift)){this.selectNone()}this.shiftFocus(a,d)}if(l){k=b.delay(100,this,d)}else{k=(function(){l=true;b(d)}).delay(400)}}.bind(this);return b}.bind(this);var h=function(){clearTimeout(k);l=false};this.keyboard.addEvents({"keydown:shift+up":n(-1),"keydown:shift+down":n(1),"keyup:shift+up":h,"keyup:shift+down":h,"keyup:up":h,"keyup:down":h});var i="";if(this.options.allowMultiSelect&&this.options.shiftForMultiSelect&&this.options.useKeyboard){i=" (Shift multi-selects)."}this.keyboard.addShortcuts({"Select Previous Row":{keys:"up",shortcut:"up arrow",handler:n(-1),description:"Select the previous row in the table."+i},"Select Next Row":{keys:"down",shortcut:"down arrow",handler:n(1),description:"Select the next row in the table."+i}})}this.keyboard[m?"activate":"deactivate"]()}this.updateSelects()},mouseleave:function(){if(this.hovered){this.leaveRow(this.hovered)}}});var Scroller=new Class({Implements:[Events,Options],options:{area:20,velocity:1,onChange:function(d,c){this.element.scrollTo(d,c)},fps:50},initialize:function(c,d){this.setOptions(d);this.element=document.id(c);this.docBody=document.id(this.element.getDocument().body);this.listener=(typeOf(this.element)!="element")?this.docBody:this.element;this.timer=null;this.bound={attach:this.attach.bind(this),detach:this.detach.bind(this),getCoords:this.getCoords.bind(this)}},start:function(){this.listener.addEvents({mouseover:this.bound.attach,mouseleave:this.bound.detach});return this},stop:function(){this.listener.removeEvents({mouseover:this.bound.attach,mouseleave:this.bound.detach});this.detach();this.timer=clearInterval(this.timer);return this},attach:function(){this.listener.addEvent("mousemove",this.bound.getCoords)},detach:function(){this.listener.removeEvent("mousemove",this.bound.getCoords);this.timer=clearInterval(this.timer)},getCoords:function(b){this.page=(this.listener.get("tag")=="body")?b.client:b.page;if(!this.timer){this.timer=this.scroll.periodical(Math.round(1000/this.options.fps),this)}},scroll:function(){var p=this.element.getSize(),j=this.element.getScroll(),k=this.element!=this.docBody?this.element.getOffsets():{x:0,y:0},o=this.element.getScrollSize(),l={x:0,y:0},n=this.options.area.top||this.options.area,i=this.options.area.bottom||this.options.area;for(var m in this.page){if(this.page[m]<(n+k[m])&&j[m]!=0){l[m]=(this.page[m]-n-k[m])*this.options.velocity}else{if(this.page[m]+i>(p[m]+k[m])&&j[m]+p[m]!=o[m]){l[m]=(this.page[m]-p[m]+i-k[m])*this.options.velocity}}l[m]=l[m].round()}if(l.y||l.x){this.fireEvent("change",[j.x+l.x,j.y+l.y])}}});(function(){var b=function(d,a){return(d)?(typeOf(d)=="function"?d(a):a.get(d)):""};this.Tips=new Class({Implements:[Events,Options],options:{onShow:function(){this.tip.setStyle("display","block")},onHide:function(){this.tip.setStyle("display","none")},title:"title",text:function(a){return a.get("rel")||a.get("href")},showDelay:100,hideDelay:100,className:"tip-wrap",offset:{x:16,y:16},windowPadding:{x:0,y:0},fixed:false,waiAria:true},initialize:function(){var a=Array.link(arguments,{options:Type.isObject,elements:function(d){return d!=null}});this.setOptions(a.options);if(a.elements){this.attach(a.elements)}this.container=new Element("div",{"class":"tip"});if(this.options.id){this.container.set("id",this.options.id);if(this.options.waiAria){this.attachWaiAria()}}},toElement:function(){if(this.tip){return this.tip}this.tip=new Element("div",{"class":this.options.className,styles:{position:"absolute",top:0,left:0}}).adopt(new Element("div",{"class":"tip-top"}),this.container,new Element("div",{"class":"tip-bottom"}));return this.tip},attachWaiAria:function(){var a=this.options.id;this.container.set("role","tooltip");if(!this.waiAria){this.waiAria={show:function(d){if(a){d.set("aria-describedby",a)}this.container.set("aria-hidden","false")},hide:function(d){if(a){d.erase("aria-describedby")}this.container.set("aria-hidden","true")}}}this.addEvents(this.waiAria)},detachWaiAria:function(){if(this.waiAria){this.container.erase("role");this.container.erase("aria-hidden");this.removeEvents(this.waiAria)}},attach:function(a){$$(a).each(function(i){var g=b(this.options.title,i),h=b(this.options.text,i);i.set("title","").store("tip:native",g).retrieve("tip:title",g);i.retrieve("tip:text",h);this.fireEvent("attach",[i]);var j=["enter","leave"];if(!this.options.fixed){j.push("move")}j.each(function(c){var d=i.retrieve("tip:"+c);if(!d){d=function(e){this["element"+c.capitalize()].apply(this,[e,i])}.bind(this)}i.store("tip:"+c,d).addEvent("mouse"+c,d)},this)},this);return this},detach:function(a){$$(a).each(function(e){["enter","leave","move"].each(function(c){e.removeEvent("mouse"+c,e.retrieve("tip:"+c)).eliminate("tip:"+c)});this.fireEvent("detach",[e]);if(this.options.title=="title"){var f=e.retrieve("tip:native");if(f){e.set("title",f)}}},this);return this},elementEnter:function(d,a){clearTimeout(this.timer);this.timer=(function(){this.container.empty();["title","text"].each(function(g){var h=a.retrieve("tip:"+g);var c=this["_"+g+"Element"]=new Element("div",{"class":"tip-"+g}).inject(this.container);if(h){this.fill(c,h)}},this);this.show(a);this.position((this.options.fixed)?{page:a.getPosition()}:d)}).delay(this.options.showDelay,this)},elementLeave:function(d,a){clearTimeout(this.timer);this.timer=this.hide.delay(this.options.hideDelay,this,a);this.fireForParent(d,a)},setTitle:function(a){if(this._titleElement){this._titleElement.empty();this.fill(this._titleElement,a)}return this},setText:function(a){if(this._textElement){this._textElement.empty();this.fill(this._textElement,a)}return this},fireForParent:function(d,a){a=a.getParent();if(!a||a==document.body){return}if(a.retrieve("tip:enter")){a.fireEvent("mouseenter",d)}else{this.fireForParent(d,a)}},elementMove:function(d,a){this.position(d)},position:function(m){if(!this.tip){document.id(this)}var p=window.getSize(),a=window.getScroll(),l={x:this.tip.offsetWidth,y:this.tip.offsetHeight},o={x:"left",y:"top"},n={y:false,x2:false,y2:false,x:false},k={};for(var j in o){k[o[j]]=m.page[j]+this.options.offset[j];if(k[o[j]]<0){n[j]=true}if((k[o[j]]+l[j]-a[j])>p[j]-this.options.windowPadding[j]){k[o[j]]=m.page[j]-this.options.offset[j]-l[j];n[j+"2"]=true}}this.fireEvent("bound",n);this.tip.setStyles(k)},fill:function(a,d){if(typeof d=="string"){a.set("html",d)}else{a.adopt(d)}},show:function(a){if(!this.tip){document.id(this)}if(!this.tip.getParent()){this.tip.inject(document.body)}this.fireEvent("show",[this.tip,a])},hide:function(a){if(!this.tip){document.id(this)}this.fireEvent("hide",[this.tip,a])}})})();(function(){var b={json:JSON.decode};Locale.Set.defineParser=function(a,d){b[a]=d};Locale.Set.from=function(e,f){if(instanceOf(e,Locale.Set)){return e}if(!f&&typeOf(e)=="string"){f="json"}if(b[f]){e=b[f](e)}var a=new Locale.Set;a.sets=e.sets||{};if(e.inherits){a.inherits.locales=Array.from(e.inherits.locales);a.inherits.sets=e.inherits.sets||{}}return a}})();Locale.define("en-GB","Date",{dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M"}).inherit("en-US","Date");Locale.define("af-ZA","Date",{months:["Januarie","Februarie","Maart","April","Mei","Junie","Julie","Augustus","September","Oktober","November","Desember"],months_abbr:["Jan","Feb","Mrt","Apr","Mei","Jun","Jul","Aug","Sep","Okt","Nov","Des"],days:["Sondag","Maandag","Dinsdag","Woensdag","Donderdag","Vrydag","Saterdag"],days_abbr:["Son","Maa","Din","Woe","Don","Vry","Sat"],dateOrder:["date","month","year"],shortDate:"%d-%m-%Y",shortTime:"%H:%M",AM:"VM",PM:"NM",firstDayOfWeek:1,ordinal:function(b){return((b>1&&b<20&&b!=8)||(b>100&&b.toString().substr(-2,1)=="1"))?"de":"ste"},lessThanMinuteAgo:"minder as 'n minuut gelede",minuteAgo:"ongeveer 'n minuut gelede",minutesAgo:"{delta} minute gelede",hourAgo:"omtret 'n uur gelede",hoursAgo:"ongeveer {delta} ure gelede",dayAgo:"1 dag gelede",daysAgo:"{delta} dae gelede",weekAgo:"1 week gelede",weeksAgo:"{delta} weke gelede",monthAgo:"1 maand gelede",monthsAgo:"{delta} maande gelede",yearAgo:"1 jaar gelede",yearsAgo:"{delta} jare gelede",lessThanMinuteUntil:"oor minder as 'n minuut",minuteUntil:"oor ongeveer 'n minuut",minutesUntil:"oor {delta} minute",hourUntil:"oor ongeveer 'n uur",hoursUntil:"oor {delta} uur",dayUntil:"oor ongeveer 'n dag",daysUntil:"oor {delta} dae",weekUntil:"oor 'n week",weeksUntil:"oor {delta} weke",monthUntil:"oor 'n maand",monthsUntil:"oor {delta} maande",yearUntil:"oor 'n jaar",yearsUntil:"oor {delta} jaar"});Locale.define("af-ZA","FormValidator",{required:"Hierdie veld word vereis.",length:"Voer asseblief {length} karakters in (u het {elLength} karakters ingevoer)",minLength:"Voer asseblief ten minste {minLength} karakters in (u het {length} karakters ingevoer).",maxLength:"Moet asseblief nie meer as {maxLength} karakters invoer nie (u het {length} karakters ingevoer).",integer:"Voer asseblief 'n heelgetal in hierdie veld in. Getalle met desimale (bv. 1.25) word nie toegelaat nie.",numeric:'Voer asseblief slegs numeriese waardes in hierdie veld in (bv. "1" of "1.1" of "-1" of "-1.1").',digits:"Gebruik asseblief slegs nommers en punktuasie in hierdie veld. (by voorbeeld, 'n telefoon nommer wat koppeltekens en punte bevat is toelaatbaar).",alpha:"Gebruik asseblief slegs letters (a-z) binne-in hierdie veld. Geen spasies of ander karakters word toegelaat nie.",alphanum:"Gebruik asseblief slegs letters (a-z) en nommers (0-9) binne-in hierdie veld. Geen spasies of ander karakters word toegelaat nie.",dateSuchAs:"Voer asseblief 'n geldige datum soos {date} in",dateInFormatMDY:'Voer asseblief \'n geldige datum soos MM/DD/YYYY in (bv. "12/31/1999")',email:'Voer asseblief \'n geldige e-pos adres in. Byvoorbeeld "fred@domain.com".',url:"Voer asseblief 'n geldige bronadres (URL) soos http://www.example.com in.",currencyDollar:"Voer asseblief 'n geldige $ bedrag in. Byvoorbeeld $100.00 .",oneRequired:"Voer asseblief iets in vir ten minste een van hierdie velde.",errorPrefix:"Fout: ",warningPrefix:"Waarskuwing: ",noSpace:"Daar mag geen spasies in hierdie toevoer wees nie.",reqChkByNode:"Geen items is gekies nie.",requiredChk:"Hierdie veld word vereis.",reqChkByName:"Kies asseblief 'n {label}.",match:"Hierdie veld moet by die {matchName} veld pas",startDate:"die begin datum",endDate:"die eind datum",currentDate:"die huidige datum",afterDate:"Die datum moet dieselfde of na {label} wees.",beforeDate:"Die datum moet dieselfde of voor {label} wees.",startMonth:"Kies asseblief 'n begin maand",sameMonth:"Hierdie twee datums moet in dieselfde maand wees - u moet een of beide verander.",creditcard:"Die ingevoerde kredietkaart nommer is ongeldig. Bevestig asseblief die nommer en probeer weer. {length} syfers is ingevoer."});Locale.define("ZA","Number",{decimal:".",group:",",currency:{prefix:"R "}});Locale.define("af-ZA").inherit("ZA","Number");Locale.define("ar","Date",{dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M"});Locale.define("ar","FormValidator",{required:"هذا الحقل مطلوب.",minLength:"رجاءً إدخال {minLength} أحرف على الأقل (تم إدخال {length} أحرف).",maxLength:"الرجاء عدم إدخال أكثر من {maxLength} أحرف (تم إدخال {length} أحرف).",integer:"الرجاء إدخال عدد صحيح في هذا الحقل. أي رقم ذو كسر عشري أو مئوي (مثال 1.25 ) غير مسموح.",numeric:'الرجاء إدخال قيم رقمية في هذا الحقل (مثال "1" أو "1.1" أو "-1" أو "-1.1").',digits:"الرجاء أستخدام قيم رقمية وعلامات ترقيمية فقط في هذا الحقل (مثال, رقم هاتف مع نقطة أو شحطة)",alpha:"الرجاء أستخدام أحرف فقط (ا-ي) في هذا الحقل. أي فراغات أو علامات غير مسموحة.",alphanum:"الرجاء أستخدام أحرف فقط (ا-ي) أو أرقام (0-9) فقط في هذا الحقل. أي فراغات أو علامات غير مسموحة.",dateSuchAs:"الرجاء إدخال تاريخ صحيح كالتالي {date}",dateInFormatMDY:"الرجاء إدخال تاريخ صحيح (مثال, 31-12-1999)",email:"الرجاء إدخال بريد إلكتروني صحيح.",url:"الرجاء إدخال عنوان إلكتروني صحيح مثل http://www.example.com",currencyDollar:"الرجاء إدخال قيمة $ صحيحة. مثال, 100.00$",oneRequired:"الرجاء إدخال قيمة في أحد هذه الحقول على الأقل.",errorPrefix:"خطأ: ",warningPrefix:"تحذير: "});Locale.define("ca-CA","Date",{months:["Gener","Febrer","Març","Abril","Maig","Juny","Juli","Agost","Setembre","Octubre","Novembre","Desembre"],months_abbr:["gen.","febr.","març","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],days:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte"],days_abbr:["dg","dl","dt","dc","dj","dv","ds"],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:0,ordinal:"",lessThanMinuteAgo:"fa menys d`un minut",minuteAgo:"fa un minut",minutesAgo:"fa {delta} minuts",hourAgo:"fa un hora",hoursAgo:"fa unes {delta} hores",dayAgo:"fa un dia",daysAgo:"fa {delta} dies",lessThanMinuteUntil:"menys d`un minut des d`ara",minuteUntil:"un minut des d`ara",minutesUntil:"{delta} minuts des d`ara",hourUntil:"un hora des d`ara",hoursUntil:"unes {delta} hores des d`ara",dayUntil:"1 dia des d`ara",daysUntil:"{delta} dies des d`ara"});Locale.define("ca-CA","FormValidator",{required:"Aquest camp es obligatori.",minLength:"Per favor introdueix al menys {minLength} caracters (has introduit {length} caracters).",maxLength:"Per favor introdueix no mes de {maxLength} caracters (has introduit {length} caracters).",integer:"Per favor introdueix un nombre enter en aquest camp. Nombres amb decimals (p.e. 1,25) no estan permesos.",numeric:'Per favor introdueix sols valors numerics en aquest camp (p.e. "1" o "1,1" o "-1" o "-1,1").',digits:"Per favor usa sols numeros i puntuacio en aquest camp (per exemple, un nombre de telefon amb guions i punts no esta permes).",alpha:"Per favor utilitza lletres nomes (a-z) en aquest camp. No s´admiteixen espais ni altres caracters.",alphanum:"Per favor, utilitza nomes lletres (a-z) o numeros (0-9) en aquest camp. No s´admiteixen espais ni altres caracters.",dateSuchAs:"Per favor introdueix una data valida com {date}",dateInFormatMDY:'Per favor introdueix una data valida com DD/MM/YYYY (p.e. "31/12/1999")',email:'Per favor, introdueix una adreça de correu electronic valida. Per exemple, "fred@domain.com".',url:"Per favor introdueix una URL valida com http://www.example.com.",currencyDollar:"Per favor introdueix una quantitat valida de €. Per exemple €100,00 .",oneRequired:"Per favor introdueix alguna cosa per al menys una d´aquestes entrades.",errorPrefix:"Error: ",warningPrefix:"Avis: ",noSpace:"No poden haver espais en aquesta entrada.",reqChkByNode:"No hi han elements seleccionats.",requiredChk:"Aquest camp es obligatori.",reqChkByName:"Per favor selecciona una {label}.",match:"Aquest camp necessita coincidir amb el camp {matchName}",startDate:"la data de inici",endDate:"la data de fi",currentDate:"la data actual",afterDate:"La data deu ser igual o posterior a {label}.",beforeDate:"La data deu ser igual o anterior a {label}.",startMonth:"Per favor selecciona un mes d´orige",sameMonth:"Aquestes dos dates deuen estar dins del mateix mes - deus canviar una o altra."});(function(){var b=function(f,g,h,a){if(f==1){return g}else{if(f==2||f==3||f==4){return h}else{return a}}};Locale.define("cs-CZ","Date",{months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],months_abbr:["ledna","února","března","dubna","května","června","července","srpna","září","října","listopadu","prosince"],days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],days_abbr:["ne","po","út","st","čt","pá","so"],dateOrder:["date","month","year"],shortDate:"%d.%m.%Y",shortTime:"%H:%M",AM:"dop.",PM:"odp.",firstDayOfWeek:1,ordinal:".",lessThanMinuteAgo:"před chvílí",minuteAgo:"přibližně před minutou",minutesAgo:function(a){return"před {delta} "+b(a,"minutou","minutami","minutami")},hourAgo:"přibližně před hodinou",hoursAgo:function(a){return"před {delta} "+b(a,"hodinou","hodinami","hodinami")},dayAgo:"před dnem",daysAgo:function(a){return"před {delta} "+b(a,"dnem","dny","dny")},weekAgo:"před týdnem",weeksAgo:function(a){return"před {delta} "+b(a,"týdnem","týdny","týdny")},monthAgo:"před měsícem",monthsAgo:function(a){return"před {delta} "+b(a,"měsícem","měsíci","měsíci")},yearAgo:"před rokem",yearsAgo:function(a){return"před {delta} "+b(a,"rokem","lety","lety")},lessThanMinuteUntil:"za chvíli",minuteUntil:"přibližně za minutu",minutesUntil:function(a){return"za {delta} "+b(a,"minutu","minuty","minut")},hourUntil:"přibližně za hodinu",hoursUntil:function(a){return"za {delta} "+b(a,"hodinu","hodiny","hodin")},dayUntil:"za den",daysUntil:function(a){return"za {delta} "+b(a,"den","dny","dnů")},weekUntil:"za týden",weeksUntil:function(a){return"za {delta} "+b(a,"týden","týdny","týdnů")},monthUntil:"za měsíc",monthsUntil:function(a){return"za {delta} "+b(a,"měsíc","měsíce","měsíců")},yearUntil:"za rok",yearsUntil:function(a){return"za {delta} "+b(a,"rok","roky","let")}})})();Locale.define("cs-CZ","FormValidator",{required:"Tato položka je povinná.",minLength:"Zadejte prosím alespoň {minLength} znaků (napsáno {length} znaků).",maxLength:"Zadejte prosím méně než {maxLength} znaků (nápsáno {length} znaků).",integer:"Zadejte prosím celé číslo. Desetinná čísla (např. 1.25) nejsou povolena.",numeric:'Zadejte jen číselné hodnoty (tj. "1" nebo "1.1" nebo "-1" nebo "-1.1").',digits:"Zadejte prosím pouze čísla a interpunkční znaménka(například telefonní číslo s pomlčkami nebo tečkami je povoleno).",alpha:"Zadejte prosím pouze písmena (a-z). Mezery nebo jiné znaky nejsou povoleny.",alphanum:"Zadejte prosím pouze písmena (a-z) nebo číslice (0-9). Mezery nebo jiné znaky nejsou povoleny.",dateSuchAs:"Zadejte prosím platné datum jako {date}",dateInFormatMDY:'Zadejte prosím platné datum jako MM / DD / RRRR (tj. "12/31/1999")',email:'Zadejte prosím platnou e-mailovou adresu. Například "fred@domain.com".',url:"Zadejte prosím platnou URL adresu jako http://www.example.com.",currencyDollar:"Zadejte prosím platnou částku. Například $100.00.",oneRequired:"Zadejte prosím alespoň jednu hodnotu pro tyto položky.",errorPrefix:"Chyba: ",warningPrefix:"Upozornění: ",noSpace:"V této položce nejsou povoleny mezery",reqChkByNode:"Nejsou vybrány žádné položky.",requiredChk:"Tato položka je vyžadována.",reqChkByName:"Prosím vyberte {label}.",match:"Tato položka se musí shodovat s položkou {matchName}",startDate:"datum zahájení",endDate:"datum ukončení",currentDate:"aktuální datum",afterDate:"Datum by mělo být stejné nebo větší než {label}.",beforeDate:"Datum by mělo být stejné nebo menší než {label}.",startMonth:"Vyberte počáteční měsíc.",sameMonth:"Tyto dva datumy musí být ve stejném měsíci - změňte jeden z nich.",creditcard:"Zadané číslo kreditní karty je neplatné. Prosím opravte ho. Bylo zadáno {length} čísel."});Locale.define("da-DK","Date",{months:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],months_abbr:["jan.","feb.","mar.","apr.","maj.","jun.","jul.","aug.","sep.","okt.","nov.","dec."],days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],days_abbr:["søn","man","tir","ons","tor","fre","lør"],dateOrder:["date","month","year"],shortDate:"%d-%m-%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:".",lessThanMinuteAgo:"mindre end et minut siden",minuteAgo:"omkring et minut siden",minutesAgo:"{delta} minutter siden",hourAgo:"omkring en time siden",hoursAgo:"omkring {delta} timer siden",dayAgo:"1 dag siden",daysAgo:"{delta} dage siden",weekAgo:"1 uge siden",weeksAgo:"{delta} uger siden",monthAgo:"1 måned siden",monthsAgo:"{delta} måneder siden",yearAgo:"1 år siden",yearsAgo:"{delta} år siden",lessThanMinuteUntil:"mindre end et minut fra nu",minuteUntil:"omkring et minut fra nu",minutesUntil:"{delta} minutter fra nu",hourUntil:"omkring en time fra nu",hoursUntil:"omkring {delta} timer fra nu",dayUntil:"1 dag fra nu",daysUntil:"{delta} dage fra nu",weekUntil:"1 uge fra nu",weeksUntil:"{delta} uger fra nu",monthUntil:"1 måned fra nu",monthsUntil:"{delta} måneder fra nu",yearUntil:"1 år fra nu",yearsUntil:"{delta} år fra nu"});Locale.define("da-DK","FormValidator",{required:"Feltet skal udfyldes.",minLength:"Skriv mindst {minLength} tegn (du skrev {length} tegn).",maxLength:"Skriv maksimalt {maxLength} tegn (du skrev {length} tegn).",integer:"Skriv et tal i dette felt. Decimal tal (f.eks. 1.25) er ikke tilladt.",numeric:'Skriv kun tal i dette felt (i.e. "1" eller "1.1" eller "-1" eller "-1.1").',digits:"Skriv kun tal og tegnsætning i dette felt (eksempel, et telefon nummer med bindestreg eller punktum er tilladt).",alpha:"Skriv kun bogstaver (a-z) i dette felt. Mellemrum og andre tegn er ikke tilladt.",alphanum:"Skriv kun bogstaver (a-z) eller tal (0-9) i dette felt. Mellemrum og andre tegn er ikke tilladt.",dateSuchAs:"Skriv en gyldig dato som {date}",dateInFormatMDY:'Skriv dato i formatet DD-MM-YYYY (f.eks. "31-12-1999")',email:'Skriv en gyldig e-mail adresse. F.eks "fred@domain.com".',url:'Skriv en gyldig URL adresse. F.eks "http://www.example.com".',currencyDollar:"Skriv et gldigt beløb. F.eks Kr.100.00 .",oneRequired:"Et eller flere af felterne i denne formular skal udfyldes.",errorPrefix:"Fejl: ",warningPrefix:"Advarsel: ",noSpace:"Der må ikke benyttes mellemrum i dette felt.",reqChkByNode:"Foretag et valg.",requiredChk:"Dette felt skal udfyldes.",reqChkByName:"Vælg en {label}.",match:"Dette felt skal matche {matchName} feltet",startDate:"start dato",endDate:"slut dato",currentDate:"dags dato",afterDate:"Datoen skal være større end eller lig med {label}.",beforeDate:"Datoen skal være mindre end eller lig med {label}.",startMonth:"Vælg en start måned",sameMonth:"De valgte datoer skal være i samme måned - skift en af dem."});Locale.define("de-DE","Date",{months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],months_abbr:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],days_abbr:["So","Mo","Di","Mi","Do","Fr","Sa"],dateOrder:["date","month","year"],shortDate:"%d.%m.%Y",shortTime:"%H:%M",AM:"vormittags",PM:"nachmittags",firstDayOfWeek:1,ordinal:".",lessThanMinuteAgo:"vor weniger als einer Minute",minuteAgo:"vor einer Minute",minutesAgo:"vor {delta} Minuten",hourAgo:"vor einer Stunde",hoursAgo:"vor {delta} Stunden",dayAgo:"vor einem Tag",daysAgo:"vor {delta} Tagen",weekAgo:"vor einer Woche",weeksAgo:"vor {delta} Wochen",monthAgo:"vor einem Monat",monthsAgo:"vor {delta} Monaten",yearAgo:"vor einem Jahr",yearsAgo:"vor {delta} Jahren",lessThanMinuteUntil:"in weniger als einer Minute",minuteUntil:"in einer Minute",minutesUntil:"in {delta} Minuten",hourUntil:"in ca. einer Stunde",hoursUntil:"in ca. {delta} Stunden",dayUntil:"in einem Tag",daysUntil:"in {delta} Tagen",weekUntil:"in einer Woche",weeksUntil:"in {delta} Wochen",monthUntil:"in einem Monat",monthsUntil:"in {delta} Monaten",yearUntil:"in einem Jahr",yearsUntil:"in {delta} Jahren"});Locale.define("de-CH").inherit("de-DE","Date");Locale.define("de-CH","FormValidator",{required:"Dieses Feld ist obligatorisch.",minLength:"Geben Sie bitte mindestens {minLength} Zeichen ein (Sie haben {length} Zeichen eingegeben).",maxLength:"Bitte geben Sie nicht mehr als {maxLength} Zeichen ein (Sie haben {length} Zeichen eingegeben).",integer:"Geben Sie bitte eine ganze Zahl ein. Dezimalzahlen (z.B. 1.25) sind nicht erlaubt.",numeric:"Geben Sie bitte nur Zahlenwerte in dieses Eingabefeld ein (z.B. &quot;1&quot;, &quot;1.1&quot;, &quot;-1&quot; oder &quot;-1.1&quot;).",digits:"Benutzen Sie bitte nur Zahlen und Satzzeichen in diesem Eingabefeld (erlaubt ist z.B. eine Telefonnummer mit Bindestrichen und Punkten).",alpha:"Benutzen Sie bitte nur Buchstaben (a-z) in diesem Feld. Leerzeichen und andere Zeichen sind nicht erlaubt.",alphanum:"Benutzen Sie bitte nur Buchstaben (a-z) und Zahlen (0-9) in diesem Eingabefeld. Leerzeichen und andere Zeichen sind nicht erlaubt.",dateSuchAs:"Geben Sie bitte ein g&uuml;ltiges Datum ein. Wie zum Beispiel {date}",dateInFormatMDY:"Geben Sie bitte ein g&uuml;ltiges Datum ein. Wie zum Beispiel TT.MM.JJJJ (z.B. &quot;31.12.1999&quot;)",email:"Geben Sie bitte eine g&uuml;ltige E-Mail Adresse ein. Wie zum Beispiel &quot;maria@bernasconi.ch&quot;.",url:"Geben Sie bitte eine g&uuml;ltige URL ein. Wie zum Beispiel http://www.example.com.",currencyDollar:"Geben Sie bitte einen g&uuml;ltigen Betrag in Schweizer Franken ein. Wie zum Beispiel 100.00 CHF .",oneRequired:"Machen Sie f&uuml;r mindestens eines der Eingabefelder einen Eintrag.",errorPrefix:"Fehler: ",warningPrefix:"Warnung: ",noSpace:"In diesem Eingabefeld darf kein Leerzeichen sein.",reqChkByNode:"Es wurden keine Elemente gew&auml;hlt.",requiredChk:"Dieses Feld ist obligatorisch.",reqChkByName:"Bitte w&auml;hlen Sie ein {label}.",match:"Dieses Eingabefeld muss mit dem Feld {matchName} &uuml;bereinstimmen.",startDate:"Das Anfangsdatum",endDate:"Das Enddatum",currentDate:"Das aktuelle Datum",afterDate:"Das Datum sollte zur gleichen Zeit oder sp&auml;ter sein {label}.",beforeDate:"Das Datum sollte zur gleichen Zeit oder fr&uuml;her sein {label}.",startMonth:"W&auml;hlen Sie bitte einen Anfangsmonat",sameMonth:"Diese zwei Datumsangaben m&uuml;ssen im selben Monat sein - Sie m&uuml;ssen eine von beiden ver&auml;ndern.",creditcard:"Die eingegebene Kreditkartennummer ist ung&uuml;ltig. Bitte &uuml;berpr&uuml;fen Sie diese und versuchen Sie es erneut. {length} Zahlen eingegeben."});Locale.define("de-DE","FormValidator",{required:"Dieses Eingabefeld muss ausgefüllt werden.",minLength:"Geben Sie bitte mindestens {minLength} Zeichen ein (Sie haben nur {length} Zeichen eingegeben).",maxLength:"Geben Sie bitte nicht mehr als {maxLength} Zeichen ein (Sie haben {length} Zeichen eingegeben).",integer:'Geben Sie in diesem Eingabefeld bitte eine ganze Zahl ein. Dezimalzahlen (z.B. "1.25") sind nicht erlaubt.',numeric:'Geben Sie in diesem Eingabefeld bitte nur Zahlenwerte (z.B. "1", "1.1", "-1" oder "-1.1") ein.',digits:"Geben Sie in diesem Eingabefeld bitte nur Zahlen und Satzzeichen ein (z.B. eine Telefonnummer mit Bindestrichen und Punkten ist erlaubt).",alpha:"Geben Sie in diesem Eingabefeld bitte nur Buchstaben (a-z) ein. Leerzeichen und andere Zeichen sind nicht erlaubt.",alphanum:"Geben Sie in diesem Eingabefeld bitte nur Buchstaben (a-z) und Zahlen (0-9) ein. Leerzeichen oder andere Zeichen sind nicht erlaubt.",dateSuchAs:'Geben Sie bitte ein gültiges Datum ein (z.B. "{date}").',dateInFormatMDY:'Geben Sie bitte ein gültiges Datum im Format TT.MM.JJJJ ein (z.B. "31.12.1999").',email:'Geben Sie bitte eine gültige E-Mail-Adresse ein (z.B. "max@mustermann.de").',url:'Geben Sie bitte eine gültige URL ein (z.B. "http://www.example.com").',currencyDollar:"Geben Sie bitte einen gültigen Betrag in EURO ein (z.B. 100.00€).",oneRequired:"Bitte füllen Sie mindestens ein Eingabefeld aus.",errorPrefix:"Fehler: ",warningPrefix:"Warnung: ",noSpace:"Es darf kein Leerzeichen in diesem Eingabefeld sein.",reqChkByNode:"Es wurden keine Elemente gewählt.",requiredChk:"Dieses Feld muss ausgefüllt werden.",reqChkByName:"Bitte wählen Sie ein {label}.",match:"Dieses Eingabefeld muss mit dem {matchName} Eingabefeld übereinstimmen.",startDate:"Das Anfangsdatum",endDate:"Das Enddatum",currentDate:"Das aktuelle Datum",afterDate:"Das Datum sollte zur gleichen Zeit oder später sein als {label}.",beforeDate:"Das Datum sollte zur gleichen Zeit oder früher sein als {label}.",startMonth:"Wählen Sie bitte einen Anfangsmonat",sameMonth:"Diese zwei Datumsangaben müssen im selben Monat sein - Sie müssen eines von beiden verändern.",creditcard:"Die eingegebene Kreditkartennummer ist ungültig. Bitte überprüfen Sie diese und versuchen Sie es erneut. {length} Zahlen eingegeben."});Locale.define("EU","Number",{decimal:",",group:".",currency:{prefix:"€ "}});Locale.define("de-DE").inherit("EU","Number");Locale.define("el-GR","Date",{months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],months_abbr:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],days_abbr:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%I:%M%p",AM:"πμ",PM:"μμ",firstDayOfWeek:1,ordinal:function(b){return(b>3&&b<21)?"ος":["ος"][Math.min(b%10,4)]},lessThanMinuteAgo:"λιγότερο από ένα λεπτό πριν",minuteAgo:"περίπου ένα λεπτό πριν",minutesAgo:"{delta} λεπτά πριν",hourAgo:"περίπου μια ώρα πριν",hoursAgo:"περίπου {delta} ώρες πριν",dayAgo:"1 ημέρα πριν",daysAgo:"{delta} ημέρες πριν",weekAgo:"1 εβδομάδα πριν",weeksAgo:"{delta} εβδομάδες πριν",monthAgo:"1 μήνα πριν",monthsAgo:"{delta} μήνες πριν",yearAgo:"1 χρόνο πριν",yearsAgo:"{delta} χρόνια πριν",lessThanMinuteUntil:"λιγότερο από λεπτό από τώρα",minuteUntil:"περίπου ένα λεπτό από τώρα",minutesUntil:"{delta} λεπτά από τώρα",hourUntil:"περίπου μια ώρα από τώρα",hoursUntil:"περίπου {delta} ώρες από τώρα",dayUntil:"1 ημέρα από τώρα",daysUntil:"{delta} ημέρες από τώρα",weekUntil:"1 εβδομάδα από τώρα",weeksUntil:"{delta} εβδομάδες από τώρα",monthUntil:"1 μήνας από τώρα",monthsUntil:"{delta} μήνες από τώρα",yearUntil:"1 χρόνος από τώρα",yearsUntil:"{delta} χρόνια από τώρα"});Locale.define("es-ES","Date",{months:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],months_abbr:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],days:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"],days_abbr:["dom","lun","mar","mié","juv","vie","sáb"],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"hace menos de un minuto",minuteAgo:"hace un minuto",minutesAgo:"hace {delta} minutos",hourAgo:"hace una hora",hoursAgo:"hace unas {delta} horas",dayAgo:"hace un día",daysAgo:"hace {delta} días",weekAgo:"hace una semana",weeksAgo:"hace unas {delta} semanas",monthAgo:"hace un mes",monthsAgo:"hace {delta} meses",yearAgo:"hace un año",yearsAgo:"hace {delta} años",lessThanMinuteUntil:"menos de un minuto desde ahora",minuteUntil:"un minuto desde ahora",minutesUntil:"{delta} minutos desde ahora",hourUntil:"una hora desde ahora",hoursUntil:"unas {delta} horas desde ahora",dayUntil:"un día desde ahora",daysUntil:"{delta} días desde ahora",weekUntil:"una semana desde ahora",weeksUntil:"unas {delta} semanas desde ahora",monthUntil:"un mes desde ahora",monthsUntil:"{delta} meses desde ahora",yearUntil:"un año desde ahora",yearsUntil:"{delta} años desde ahora"});Locale.define("es-AR").inherit("es-ES","Date");Locale.define("es-AR","FormValidator",{required:"Este campo es obligatorio.",minLength:"Por favor ingrese al menos {minLength} caracteres (ha ingresado {length} caracteres).",maxLength:"Por favor no ingrese más de {maxLength} caracteres (ha ingresado {length} caracteres).",integer:"Por favor ingrese un número entero en este campo. Números con decimales (p.e. 1,25) no se permiten.",numeric:'Por favor ingrese solo valores numéricos en este campo (p.e. "1" o "1,1" o "-1" o "-1,1").',digits:"Por favor use sólo números y puntuación en este campo (por ejemplo, un número de teléfono con guiones y/o puntos no está permitido).",alpha:"Por favor use sólo letras (a-z) en este campo. No se permiten espacios ni otros caracteres.",alphanum:"Por favor, usa sólo letras (a-z) o números (0-9) en este campo. No se permiten espacios u otros caracteres.",dateSuchAs:"Por favor ingrese una fecha válida como {date}",dateInFormatMDY:'Por favor ingrese una fecha válida, utulizando el formato DD/MM/YYYY (p.e. "31/12/1999")',email:'Por favor, ingrese una dirección de e-mail válida. Por ejemplo, "fred@dominio.com".',url:"Por favor ingrese una URL válida como http://www.example.com.",currencyDollar:"Por favor ingrese una cantidad válida de pesos. Por ejemplo $100,00 .",oneRequired:"Por favor ingrese algo para por lo menos una de estas entradas.",errorPrefix:"Error: ",warningPrefix:"Advertencia: ",noSpace:"No se permiten espacios en este campo.",reqChkByNode:"No hay elementos seleccionados.",requiredChk:"Este campo es obligatorio.",reqChkByName:"Por favor selecciona una {label}.",match:"Este campo necesita coincidir con el campo {matchName}",startDate:"la fecha de inicio",endDate:"la fecha de fin",currentDate:"la fecha actual",afterDate:"La fecha debe ser igual o posterior a {label}.",beforeDate:"La fecha debe ser igual o anterior a {label}.",startMonth:"Por favor selecciona un mes de origen",sameMonth:"Estas dos fechas deben estar en el mismo mes - debes cambiar una u otra."});Locale.define("es-ES","FormValidator",{required:"Este campo es obligatorio.",minLength:"Por favor introduce al menos {minLength} caracteres (has introducido {length} caracteres).",maxLength:"Por favor introduce no m&aacute;s de {maxLength} caracteres (has introducido {length} caracteres).",integer:"Por favor introduce un n&uacute;mero entero en este campo. N&uacute;meros con decimales (p.e. 1,25) no se permiten.",numeric:'Por favor introduce solo valores num&eacute;ricos en este campo (p.e. "1" o "1,1" o "-1" o "-1,1").',digits:"Por favor usa solo n&uacute;meros y puntuaci&oacute;n en este campo (por ejemplo, un n&uacute;mero de tel&eacute;fono con guiones y puntos no esta permitido).",alpha:"Por favor usa letras solo (a-z) en este campo. No se admiten espacios ni otros caracteres.",alphanum:"Por favor, usa solo letras (a-z) o n&uacute;meros (0-9) en este campo. No se admiten espacios ni otros caracteres.",dateSuchAs:"Por favor introduce una fecha v&aacute;lida como {date}",dateInFormatMDY:'Por favor introduce una fecha v&aacute;lida como DD/MM/YYYY (p.e. "31/12/1999")',email:'Por favor, introduce una direcci&oacute;n de email v&aacute;lida. Por ejemplo, "fred@domain.com".',url:"Por favor introduce una URL v&aacute;lida como http://www.example.com.",currencyDollar:"Por favor introduce una cantidad v&aacute;lida de €. Por ejemplo €100,00 .",oneRequired:"Por favor introduce algo para por lo menos una de estas entradas.",errorPrefix:"Error: ",warningPrefix:"Aviso: ",noSpace:"No pueden haber espacios en esta entrada.",reqChkByNode:"No hay elementos seleccionados.",requiredChk:"Este campo es obligatorio.",reqChkByName:"Por favor selecciona una {label}.",match:"Este campo necesita coincidir con el campo {matchName}",startDate:"la fecha de inicio",endDate:"la fecha de fin",currentDate:"la fecha actual",afterDate:"La fecha debe ser igual o posterior a {label}.",beforeDate:"La fecha debe ser igual o anterior a {label}.",startMonth:"Por favor selecciona un mes de origen",sameMonth:"Estas dos fechas deben estar en el mismo mes - debes cambiar una u otra."});Locale.define("es-VE").inherit("es-ES","Date");Locale.define("es-VE","FormValidator",{digits:"Por favor usa solo n&uacute;meros y puntuaci&oacute;n en este campo. Por ejemplo, un n&uacute;mero de tel&eacute;fono con guiones y puntos no esta permitido.",alpha:"Por favor usa solo letras (a-z) en este campo. No se admiten espacios ni otros caracteres.",currencyDollar:"Por favor introduce una cantidad v&aacute;lida de Bs. Por ejemplo Bs. 100,00 .",oneRequired:"Por favor introduce un valor para por lo menos una de estas entradas.",startDate:"La fecha de inicio",endDate:"La fecha de fin",currentDate:"La fecha actual"}).inherit("es-ES","FormValidator");Locale.define("es-VE","Number",{decimal:",",group:".",negative:{prefix:"-"},currency:{decimals:2,prefix:"Bs. "},percentage:{decimals:2,suffix:"%"}});Locale.define("et-EE","Date",{months:["jaanuar","veebruar","märts","aprill","mai","juuni","juuli","august","september","oktoober","november","detsember"],months_abbr:["jaan","veebr","märts","apr","mai","juuni","juuli","aug","sept","okt","nov","dets"],days:["pühapäev","esmaspäev","teisipäev","kolmapäev","neljapäev","reede","laupäev"],days_abbr:["pühap","esmasp","teisip","kolmap","neljap","reede","laup"],dateOrder:["month","date","year"],shortDate:"%m.%d.%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"vähem kui minut aega tagasi",minuteAgo:"umbes minut aega tagasi",minutesAgo:"{delta} minutit tagasi",hourAgo:"umbes tund aega tagasi",hoursAgo:"umbes {delta} tundi tagasi",dayAgo:"1 päev tagasi",daysAgo:"{delta} päeva tagasi",weekAgo:"1 nädal tagasi",weeksAgo:"{delta} nädalat tagasi",monthAgo:"1 kuu tagasi",monthsAgo:"{delta} kuud tagasi",yearAgo:"1 aasta tagasi",yearsAgo:"{delta} aastat tagasi",lessThanMinuteUntil:"vähem kui minuti aja pärast",minuteUntil:"umbes minuti aja pärast",minutesUntil:"{delta} minuti pärast",hourUntil:"umbes tunni aja pärast",hoursUntil:"umbes {delta} tunni pärast",dayUntil:"1 päeva pärast",daysUntil:"{delta} päeva pärast",weekUntil:"1 nädala pärast",weeksUntil:"{delta} nädala pärast",monthUntil:"1 kuu pärast",monthsUntil:"{delta} kuu pärast",yearUntil:"1 aasta pärast",yearsUntil:"{delta} aasta pärast"});Locale.define("et-EE","FormValidator",{required:"Väli peab olema täidetud.",minLength:"Palun sisestage vähemalt {minLength} tähte (te sisestasite {length} tähte).",maxLength:"Palun ärge sisestage rohkem kui {maxLength} tähte (te sisestasite {length} tähte).",integer:"Palun sisestage väljale täisarv. Kümnendarvud (näiteks 1.25) ei ole lubatud.",numeric:'Palun sisestage ainult numbreid väljale (näiteks "1", "1.1", "-1" või "-1.1").',digits:"Palun kasutage ainult numbreid ja kirjavahemärke (telefoninumbri sisestamisel on lubatud kasutada kriipse ja punkte).",alpha:"Palun kasutage ainult tähti (a-z). Tühikud ja teised sümbolid on keelatud.",alphanum:"Palun kasutage ainult tähti (a-z) või numbreid (0-9). Tühikud ja teised sümbolid on keelatud.",dateSuchAs:"Palun sisestage kehtiv kuupäev kujul {date}",dateInFormatMDY:'Palun sisestage kehtiv kuupäev kujul MM.DD.YYYY (näiteks: "12.31.1999").',email:'Palun sisestage kehtiv e-maili aadress (näiteks: "fred@domain.com").',url:"Palun sisestage kehtiv URL (näiteks: http://www.example.com).",currencyDollar:"Palun sisestage kehtiv $ summa (näiteks: $100.00).",oneRequired:"Palun sisestage midagi vähemalt ühele antud väljadest.",errorPrefix:"Viga: ",warningPrefix:"Hoiatus: ",noSpace:"Väli ei tohi sisaldada tühikuid.",reqChkByNode:"Ükski väljadest pole valitud.",requiredChk:"Välja täitmine on vajalik.",reqChkByName:"Palun valige üks {label}.",match:"Väli peab sobima {matchName} väljaga",startDate:"algkuupäev",endDate:"lõppkuupäev",currentDate:"praegune kuupäev",afterDate:"Kuupäev peab olema võrdne või pärast {label}.",beforeDate:"Kuupäev peab olema võrdne või enne {label}.",startMonth:"Palun valige algkuupäev.",sameMonth:"Antud kaks kuupäeva peavad olema samas kuus - peate muutma ühte kuupäeva."});Locale.define("fa","Date",{months:["ژانویه","فوریه","مارس","آپریل","مه","ژوئن","ژوئیه","آگوست","سپتامبر","اکتبر","نوامبر","دسامبر"],months_abbr:["1","2","3","4","5","6","7","8","9","10","11","12"],days:["یکشنبه","دوشنبه","سه شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],days_abbr:["ي","د","س","چ","پ","ج","ش"],dateOrder:["month","date","year"],shortDate:"%m/%d/%Y",shortTime:"%I:%M%p",AM:"ق.ظ",PM:"ب.ظ",ordinal:"ام",lessThanMinuteAgo:"کمتر از یک دقیقه پیش",minuteAgo:"حدود یک دقیقه پیش",minutesAgo:"{delta} دقیقه پیش",hourAgo:"حدود یک ساعت پیش",hoursAgo:"حدود {delta} ساعت پیش",dayAgo:"1 روز پیش",daysAgo:"{delta} روز پیش",weekAgo:"1 هفته پیش",weeksAgo:"{delta} هفته پیش",monthAgo:"1 ماه پیش",monthsAgo:"{delta} ماه پیش",yearAgo:"1 سال پیش",yearsAgo:"{delta} سال پیش",lessThanMinuteUntil:"کمتر از یک دقیقه از حالا",minuteUntil:"حدود یک دقیقه از حالا",minutesUntil:"{delta} دقیقه از حالا",hourUntil:"حدود یک ساعت از حالا",hoursUntil:"حدود {delta} ساعت از حالا",dayUntil:"1 روز از حالا",daysUntil:"{delta} روز از حالا",weekUntil:"1 هفته از حالا",weeksUntil:"{delta} هفته از حالا",monthUntil:"1 ماه از حالا",monthsUntil:"{delta} ماه از حالا",yearUntil:"1 سال از حالا",yearsUntil:"{delta} سال از حالا"});Locale.define("fa","FormValidator",{required:"این فیلد الزامی است.",minLength:"شما باید حداقل {minLength} حرف وارد کنید ({length} حرف وارد کرده اید).",maxLength:"لطفا حداکثر {maxLength} حرف وارد کنید (شما {length} حرف وارد کرده اید).",integer:"لطفا از عدد صحیح استفاده کنید. اعداد اعشاری (مانند 1.25) مجاز نیستند.",numeric:'لطفا فقط داده عددی وارد کنید (مانند "1" یا "1.1" یا "1-" یا "1.1-").',digits:"لطفا فقط از اعداد و علامتها در این فیلد استفاده کنید (برای مثال شماره تلفن با خط تیره و نقطه قابل قبول است).",alpha:"لطفا فقط از حروف الفباء برای این بخش استفاده کنید. کاراکترهای دیگر و فاصله مجاز نیستند.",alphanum:"لطفا فقط از حروف الفباء و اعداد در این بخش استفاده کنید. کاراکترهای دیگر و فاصله مجاز نیستند.",dateSuchAs:"لطفا یک تاریخ معتبر مانند {date} وارد کنید.",dateInFormatMDY:'لطفا یک تاریخ معتبر به شکل MM/DD/YYYY وارد کنید (مانند "12/31/1999").',email:'لطفا یک آدرس ایمیل معتبر وارد کنید. برای مثال "fred@domain.com".',url:"لطفا یک URL معتبر مانند http://www.example.com وارد کنید.",currencyDollar:"لطفا یک محدوده معتبر برای این بخش وارد کنید مانند 100.00$ .",oneRequired:"لطفا حداقل یکی از فیلدها را پر کنید.",errorPrefix:"خطا: ",warningPrefix:"هشدار: ",noSpace:"استفاده از فاصله در این بخش مجاز نیست.",reqChkByNode:"موردی انتخاب نشده است.",requiredChk:"این فیلد الزامی است.",reqChkByName:"لطفا یک {label} را انتخاب کنید.",match:"این فیلد باید با فیلد {matchName} مطابقت داشته باشد.",startDate:"تاریخ شروع",endDate:"تاریخ پایان",currentDate:"تاریخ کنونی",afterDate:"تاریخ میبایست برابر یا بعد از {label} باشد",beforeDate:"تاریخ میبایست برابر یا قبل از {label} باشد",startMonth:"لطفا ماه شروع را انتخاب کنید",sameMonth:"این دو تاریخ باید در یک ماه باشند - شما باید یکی یا هر دو را تغییر دهید.",creditcard:"شماره کارت اعتباری که وارد کرده اید معتبر نیست. لطفا شماره را بررسی کنید و مجددا تلاش کنید. {length} رقم وارد شده است."});Locale.define("fi-FI","Date",{months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],months_abbr:["tammik.","helmik.","maalisk.","huhtik.","toukok.","kesäk.","heinäk.","elok.","syysk.","lokak.","marrask.","jouluk."],days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],days_abbr:["su","ma","ti","ke","to","pe","la"],dateOrder:["date","month","year"],shortDate:"%d.%m.%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:".",lessThanMinuteAgo:"vajaa minuutti sitten",minuteAgo:"noin minuutti sitten",minutesAgo:"{delta} minuuttia sitten",hourAgo:"noin tunti sitten",hoursAgo:"noin {delta} tuntia sitten",dayAgo:"päivä sitten",daysAgo:"{delta} päivää sitten",weekAgo:"viikko sitten",weeksAgo:"{delta} viikkoa sitten",monthAgo:"kuukausi sitten",monthsAgo:"{delta} kuukautta sitten",yearAgo:"vuosi sitten",yearsAgo:"{delta} vuotta sitten",lessThanMinuteUntil:"vajaan minuutin kuluttua",minuteUntil:"noin minuutin kuluttua",minutesUntil:"{delta} minuutin kuluttua",hourUntil:"noin tunnin kuluttua",hoursUntil:"noin {delta} tunnin kuluttua",dayUntil:"päivän kuluttua",daysUntil:"{delta} päivän kuluttua",weekUntil:"viikon kuluttua",weeksUntil:"{delta} viikon kuluttua",monthUntil:"kuukauden kuluttua",monthsUntil:"{delta} kuukauden kuluttua",yearUntil:"vuoden kuluttua",yearsUntil:"{delta} vuoden kuluttua"});Locale.define("fi-FI","FormValidator",{required:"Tämä kenttä on pakollinen.",minLength:"Ole hyvä ja anna vähintään {minLength} merkkiä (annoit {length} merkkiä).",maxLength:"Älä anna enempää kuin {maxLength} merkkiä (annoit {length} merkkiä).",integer:"Ole hyvä ja anna kokonaisluku. Luvut, joissa on desimaaleja (esim. 1.25) eivät ole sallittuja.",numeric:'Anna tähän kenttään lukuarvo (kuten "1" tai "1.1" tai "-1" tai "-1.1").',digits:"Käytä pelkästään numeroita ja välimerkkejä tässä kentässä (syötteet, kuten esim. puhelinnumero, jossa on väliviivoja, pilkkuja tai pisteitä, kelpaa).",alpha:"Anna tähän kenttään vain kirjaimia (a-z). Välilyönnit tai muut merkit eivät ole sallittuja.",alphanum:"Anna tähän kenttään vain kirjaimia (a-z) tai numeroita (0-9). Välilyönnit tai muut merkit eivät ole sallittuja.",dateSuchAs:"Ole hyvä ja anna kelvollinen päivmäärä, kuten esimerkiksi {date}",dateInFormatMDY:'Ole hyvä ja anna kelvollinen päivämäärä muodossa pp/kk/vvvv (kuten "12/31/1999")',email:'Ole hyvä ja anna kelvollinen sähköpostiosoite (kuten esimerkiksi "matti@meikalainen.com").',url:"Ole hyvä ja anna kelvollinen URL, kuten esimerkiksi http://www.example.com.",currencyDollar:"Ole hyvä ja anna kelvollinen eurosumma (kuten esimerkiksi 100,00 EUR) .",oneRequired:"Ole hyvä ja syötä jotakin ainakin johonkin näistä kentistä.",errorPrefix:"Virhe: ",warningPrefix:"Varoitus: ",noSpace:"Tässä syötteessä ei voi olla välilyöntejä",reqChkByNode:"Ei valintoja.",requiredChk:"Tämä kenttä on pakollinen.",reqChkByName:"Ole hyvä ja valitse {label}.",match:"Tämän kentän tulee vastata kenttää {matchName}",startDate:"alkupäivämäärä",endDate:"loppupäivämäärä",currentDate:"nykyinen päivämäärä",afterDate:"Päivämäärän tulisi olla sama tai myöhäisempi ajankohta kuin {label}.",beforeDate:"Päivämäärän tulisi olla sama tai aikaisempi ajankohta kuin {label}.",startMonth:"Ole hyvä ja valitse aloituskuukausi",sameMonth:"Näiden kahden päivämäärän tulee olla saman kuun sisällä -- sinun pitää muuttaa jompaa kumpaa.",creditcard:"Annettu luottokortin numero ei kelpaa. Ole hyvä ja tarkista numero sekä yritä uudelleen. {length} numeroa syötetty."});Locale.define("fi-FI","Number",{group:" "}).inherit("EU","Number");Locale.define("fr-FR","Date",{months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],months_abbr:["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],days_abbr:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:function(b){return(b>1)?"":"er"},lessThanMinuteAgo:"il y a moins d'une minute",minuteAgo:"il y a une minute",minutesAgo:"il y a {delta} minutes",hourAgo:"il y a une heure",hoursAgo:"il y a {delta} heures",dayAgo:"il y a un jour",daysAgo:"il y a {delta} jours",weekAgo:"il y a une semaine",weeksAgo:"il y a {delta} semaines",monthAgo:"il y a 1 mois",monthsAgo:"il y a {delta} mois",yearthAgo:"il y a 1 an",yearsAgo:"il y a {delta} ans",lessThanMinuteUntil:"dans moins d'une minute",minuteUntil:"dans une minute",minutesUntil:"dans {delta} minutes",hourUntil:"dans une heure",hoursUntil:"dans {delta} heures",dayUntil:"dans un jour",daysUntil:"dans {delta} jours",weekUntil:"dans 1 semaine",weeksUntil:"dans {delta} semaines",monthUntil:"dans 1 mois",monthsUntil:"dans {delta} mois",yearUntil:"dans 1 an",yearsUntil:"dans {delta} ans"});Locale.define("fr-FR","FormValidator",{required:"Ce champ est obligatoire.",length:"Veuillez saisir {length} caract&egrave;re(s) (vous avez saisi {elLength} caract&egrave;re(s)",minLength:"Veuillez saisir un minimum de {minLength} caract&egrave;re(s) (vous avez saisi {length} caract&egrave;re(s)).",maxLength:"Veuillez saisir un maximum de {maxLength} caract&egrave;re(s) (vous avez saisi {length} caract&egrave;re(s)).",integer:'Veuillez saisir un nombre entier dans ce champ. Les nombres d&eacute;cimaux (ex : "1,25") ne sont pas autoris&eacute;s.',numeric:'Veuillez saisir uniquement des chiffres dans ce champ (ex : "1" ou "1,1" ou "-1" ou "-1,1").',digits:"Veuillez saisir uniquement des chiffres et des signes de ponctuation dans ce champ (ex : un num&eacute;ro de t&eacute;l&eacute;phone avec des traits d'union est autoris&eacute;).",alpha:"Veuillez saisir uniquement des lettres (a-z) dans ce champ. Les espaces ou autres caract&egrave;res ne sont pas autoris&eacute;s.",alphanum:"Veuillez saisir uniquement des lettres (a-z) ou des chiffres (0-9) dans ce champ. Les espaces ou autres caract&egrave;res ne sont pas autoris&eacute;s.",dateSuchAs:"Veuillez saisir une date correcte comme {date}",dateInFormatMDY:'Veuillez saisir une date correcte, au format JJ/MM/AAAA (ex : "31/11/1999").',email:'Veuillez saisir une adresse de courrier &eacute;lectronique. Par exemple "fred@domaine.com".',url:"Veuillez saisir une URL, comme http://www.exemple.com.",currencyDollar:"Veuillez saisir une quantit&eacute; correcte. Par exemple 100,00&euro;.",oneRequired:"Veuillez s&eacute;lectionner au moins une de ces options.",errorPrefix:"Erreur : ",warningPrefix:"Attention : ",noSpace:"Ce champ n'accepte pas les espaces.",reqChkByNode:"Aucun &eacute;l&eacute;ment n'est s&eacute;lectionn&eacute;.",requiredChk:"Ce champ est obligatoire.",reqChkByName:"Veuillez s&eacute;lectionner un(e) {label}.",match:"Ce champ doit correspondre avec le champ {matchName}.",startDate:"date de d&eacute;but",endDate:"date de fin",currentDate:"date actuelle",afterDate:"La date doit &ecirc;tre identique ou post&eacute;rieure &agrave; {label}.",beforeDate:"La date doit &ecirc;tre identique ou ant&eacute;rieure &agrave; {label}.",startMonth:"Veuillez s&eacute;lectionner un mois de d&eacute;but.",sameMonth:"Ces deux dates doivent &ecirc;tre dans le m&ecirc;me mois - vous devez en modifier une.",creditcard:"Le num&eacute;ro de carte de cr&eacute;dit est invalide. Merci de v&eacute;rifier le num&eacute;ro et de r&eacute;essayer. Vous avez entr&eacute; {length} chiffre(s)."});Locale.define("fr-FR","Number",{group:" "}).inherit("EU","Number");Locale.define("he-IL","Date",{months:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],months_abbr:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],days:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת"],days_abbr:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת"],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:0,ordinal:"",lessThanMinuteAgo:"לפני פחות מדקה",minuteAgo:"לפני כדקה",minutesAgo:"לפני {delta} דקות",hourAgo:"לפני כשעה",hoursAgo:"לפני {delta} שעות",dayAgo:"לפני יום",daysAgo:"לפני {delta} ימים",weekAgo:"לפני שבוע",weeksAgo:"לפני {delta} שבועות",monthAgo:"לפני חודש",monthsAgo:"לפני {delta} חודשים",yearAgo:"לפני שנה",yearsAgo:"לפני {delta} שנים",lessThanMinuteUntil:"בעוד פחות מדקה",minuteUntil:"בעוד כדקה",minutesUntil:"בעוד {delta} דקות",hourUntil:"בעוד כשעה",hoursUntil:"בעוד {delta} שעות",dayUntil:"בעוד יום",daysUntil:"בעוד {delta} ימים",weekUntil:"בעוד שבוע",weeksUntil:"בעוד {delta} שבועות",monthUntil:"בעוד חודש",monthsUntil:"בעוד {delta} חודשים",yearUntil:"בעוד שנה",yearsUntil:"בעוד {delta} שנים"});Locale.define("he-IL","FormValidator",{required:"נא למלא שדה זה.",minLength:"נא להזין לפחות {minLength} תווים (הזנת {length} תווים).",maxLength:"נא להזין עד {maxLength} תווים (הזנת {length} תווים).",integer:"נא להזין מספר שלם לשדה זה. מספרים עשרוניים (כמו 1.25) אינם חוקיים.",numeric:'נא להזין ערך מספרי בלבד בשדה זה (כמו "1", "1.1", "-1" או "-1.1").',digits:"נא להזין רק ספרות וסימני הפרדה בשדה זה (למשל, מספר טלפון עם מקפים או נקודות הוא חוקי).",alpha:"נא להזין רק אותיות באנגלית (a-z) בשדה זה. רווחים או תווים אחרים אינם חוקיים.",alphanum:"נא להזין רק אותריות באנגלית (a-z) או ספרות (0-9) בשדה זה. אווחרים או תווים אחרים אינם חוקיים.",dateSuchAs:"נא להזין תאריך חוקי, כמו {date}",dateInFormatMDY:'נא להזין תאריך חוקי בפורמט MM/DD/YYYY (כמו "12/31/1999")',email:'נא להזין כתובת אימייל חוקית. לדוגמה: "fred@domain.com".',url:"נא להזין כתובת אתר חוקית, כמו http://www.example.com.",currencyDollar:"נא להזין סכום דולרי חוקי. לדוגמה $100.00.",oneRequired:"נא לבחור לפחות בשדה אחד.",errorPrefix:"שגיאה: ",warningPrefix:"אזהרה: ",noSpace:"אין להזין רווחים בשדה זה.",reqChkByNode:"נא לבחור אחת מהאפשרויות.",requiredChk:"שדה זה נדרש.",reqChkByName:"נא לבחור {label}.",match:"שדה זה צריך להתאים לשדה {matchName}",startDate:"תאריך ההתחלה",endDate:"תאריך הסיום",currentDate:"התאריך הנוכחי",afterDate:"התאריך צריך להיות זהה או אחרי {label}.",beforeDate:"התאריך צריך להיות זהה או לפני {label}.",startMonth:"נא לבחור חודש התחלה",sameMonth:"שני תאריכים אלה צריכים להיות באותו חודש - נא לשנות אחד התאריכים.",creditcard:"מספר כרטיס האשראי שהוזן אינו חוקי. נא לבדוק שנית. הוזנו {length} ספרות."});Locale.define("he-IL","Number",{decimal:".",group:",",currency:{suffix:" ₪"}});Locale.define("hu-HU","Date",{months:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],months_abbr:["jan.","febr.","márc.","ápr.","máj.","jún.","júl.","aug.","szept.","okt.","nov.","dec."],days:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat"],days_abbr:["V","H","K","Sze","Cs","P","Szo"],dateOrder:["year","month","date"],shortDate:"%Y.%m.%d.",shortTime:"%I:%M",AM:"de.",PM:"du.",firstDayOfWeek:1,ordinal:".",lessThanMinuteAgo:"alig egy perce",minuteAgo:"egy perce",minutesAgo:"{delta} perce",hourAgo:"egy órája",hoursAgo:"{delta} órája",dayAgo:"1 napja",daysAgo:"{delta} napja",weekAgo:"1 hete",weeksAgo:"{delta} hete",monthAgo:"1 hónapja",monthsAgo:"{delta} hónapja",yearAgo:"1 éve",yearsAgo:"{delta} éve",lessThanMinuteUntil:"alig egy perc múlva",minuteUntil:"egy perc múlva",minutesUntil:"{delta} perc múlva",hourUntil:"egy óra múlva",hoursUntil:"{delta} óra múlva",dayUntil:"1 nap múlva",daysUntil:"{delta} nap múlva",weekUntil:"1 hét múlva",weeksUntil:"{delta} hét múlva",monthUntil:"1 hónap múlva",monthsUntil:"{delta} hónap múlva",yearUntil:"1 év múlva",yearsUntil:"{delta} év múlva"});Locale.define("hu-HU","FormValidator",{required:"A mező kitöltése kötelező.",minLength:"Legalább {minLength} karakter megadása szükséges (megadva {length} karakter).",maxLength:"Legfeljebb {maxLength} karakter megadása lehetséges (megadva {length} karakter).",integer:"Egész szám megadása szükséges. A tizedesjegyek (pl. 1.25) nem engedélyezettek.",numeric:'Szám megadása szükséges (pl. "1" vagy "1.1" vagy "-1" vagy "-1.1").',digits:"Csak számok és írásjelek megadása lehetséges (pl. telefonszám kötőjelek és/vagy perjelekkel).",alpha:"Csak betűk (a-z) megadása lehetséges. Szóköz és egyéb karakterek nem engedélyezettek.",alphanum:"Csak betűk (a-z) vagy számok (0-9) megadása lehetséges. Szóköz és egyéb karakterek nem engedélyezettek.",dateSuchAs:"Valós dátum megadása szükséges (pl. {date}).",dateInFormatMDY:'Valós dátum megadása szükséges ÉÉÉÉ.HH.NN. formában. (pl. "1999.12.31.")',email:'Valós e-mail cím megadása szükséges (pl. "fred@domain.hu").',url:"Valós URL megadása szükséges (pl. http://www.example.com).",currencyDollar:"Valós pénzösszeg megadása szükséges (pl. 100.00 Ft.).",oneRequired:"Az alábbi mezők legalább egyikének kitöltése kötelező.",errorPrefix:"Hiba: ",warningPrefix:"Figyelem: ",noSpace:"A mező nem tartalmazhat szóközöket.",reqChkByNode:"Nincs egyetlen kijelölt elem sem.",requiredChk:"A mező kitöltése kötelező.",reqChkByName:"Egy {label} kiválasztása szükséges.",match:"A mezőnek egyeznie kell a(z) {matchName} mezővel.",startDate:"a kezdet dátuma",endDate:"a vég dátuma",currentDate:"jelenlegi dátum",afterDate:"A dátum nem lehet kisebb, mint {label}.",beforeDate:"A dátum nem lehet nagyobb, mint {label}.",startMonth:"Kezdeti hónap megadása szükséges.",sameMonth:"A két dátumnak ugyanazon hónapban kell lennie.",creditcard:"A megadott bankkártyaszám nem valódi (megadva {length} számjegy)."});Locale.define("it-IT","Date",{months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],months_abbr:["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],days_abbr:["dom","lun","mar","mer","gio","ven","sab"],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H.%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"º",lessThanMinuteAgo:"meno di un minuto fa",minuteAgo:"circa un minuto fa",minutesAgo:"circa {delta} minuti fa",hourAgo:"circa un'ora fa",hoursAgo:"circa {delta} ore fa",dayAgo:"circa 1 giorno fa",daysAgo:"circa {delta} giorni fa",weekAgo:"una settimana fa",weeksAgo:"{delta} settimane fa",monthAgo:"un mese fa",monthsAgo:"{delta} mesi fa",yearAgo:"un anno fa",yearsAgo:"{delta} anni fa",lessThanMinuteUntil:"tra meno di un minuto",minuteUntil:"tra circa un minuto",minutesUntil:"tra circa {delta} minuti",hourUntil:"tra circa un'ora",hoursUntil:"tra circa {delta} ore",dayUntil:"tra circa un giorno",daysUntil:"tra circa {delta} giorni",weekUntil:"tra una settimana",weeksUntil:"tra {delta} settimane",monthUntil:"tra un mese",monthsUntil:"tra {delta} mesi",yearUntil:"tra un anno",yearsUntil:"tra {delta} anni"});Locale.define("it-IT","FormValidator",{required:"Il campo &egrave; obbligatorio.",minLength:"Inserire almeno {minLength} caratteri (ne sono stati inseriti {length}).",maxLength:"Inserire al massimo {maxLength} caratteri (ne sono stati inseriti {length}).",integer:"Inserire un numero intero. Non sono consentiti decimali (es.: 1.25).",numeric:'Inserire solo valori numerici (es.: "1" oppure "1.1" oppure "-1" oppure "-1.1").',digits:"Inserire solo numeri e caratteri di punteggiatura. Per esempio &egrave; consentito un numero telefonico con trattini o punti.",alpha:"Inserire solo lettere (a-z). Non sono consentiti spazi o altri caratteri.",alphanum:"Inserire solo lettere (a-z) o numeri (0-9). Non sono consentiti spazi o altri caratteri.",dateSuchAs:"Inserire una data valida del tipo {date}",dateInFormatMDY:'Inserire una data valida nel formato MM/GG/AAAA (es.: "12/31/1999")',email:'Inserire un indirizzo email valido. Per esempio "nome@dominio.com".',url:'Inserire un indirizzo valido. Per esempio "http://www.example.com".',currencyDollar:'Inserire un importo valido. Per esempio "$100.00".',oneRequired:"Completare almeno uno dei campi richiesti.",errorPrefix:"Errore: ",warningPrefix:"Attenzione: ",noSpace:"Non sono consentiti spazi.",reqChkByNode:"Nessuna voce selezionata.",requiredChk:"Il campo &egrave; obbligatorio.",reqChkByName:"Selezionare un(a) {label}.",match:"Il valore deve corrispondere al campo {matchName}",startDate:"data d'inizio",endDate:"data di fine",currentDate:"data attuale",afterDate:"La data deve corrispondere o essere successiva al {label}.",beforeDate:"La data deve corrispondere o essere precedente al {label}.",startMonth:"Selezionare un mese d'inizio",sameMonth:"Le due date devono essere dello stesso mese - occorre modificarne una."});Locale.define("ja-JP","Date",{months:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],months_abbr:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],days:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],days_abbr:["日","月","火","水","木","金","土"],dateOrder:["year","month","date"],shortDate:"%Y/%m/%d",shortTime:"%H:%M",AM:"午前",PM:"午後",firstDayOfWeek:0,ordinal:"",lessThanMinuteAgo:"1分以内前",minuteAgo:"約1分前",minutesAgo:"約{delta}分前",hourAgo:"約1時間前",hoursAgo:"約{delta}時間前",dayAgo:"1日前",daysAgo:"{delta}日前",weekAgo:"1週間前",weeksAgo:"{delta}週間前",monthAgo:"1ヶ月前",monthsAgo:"{delta}ヶ月前",yearAgo:"1年前",yearsAgo:"{delta}年前",lessThanMinuteUntil:"今から約1分以内",minuteUntil:"今から約1分",minutesUntil:"今から約{delta}分",hourUntil:"今から約1時間",hoursUntil:"今から約{delta}時間",dayUntil:"今から1日間",daysUntil:"今から{delta}日間",weekUntil:"今から1週間",weeksUntil:"今から{delta}週間",monthUntil:"今から1ヶ月",monthsUntil:"今から{delta}ヶ月",yearUntil:"今から1年",yearsUntil:"今から{delta}年"});Locale.define("ja-JP","FormValidator",{required:"入力は必須です。",minLength:"入力文字数は{minLength}以上にしてください。({length}文字)",maxLength:"入力文字数は{maxLength}以下にしてください。({length}文字)",integer:"整数を入力してください。",numeric:'入力できるのは数値だけです。(例: "1", "1.1", "-1", "-1.1"....)',digits:"入力できるのは数値と句読記号です。 (例: -や+を含む電話番号など).",alpha:"入力できるのは半角英字だけです。それ以外の文字は入力できません。",alphanum:"入力できるのは半角英数字だけです。それ以外の文字は入力できません。",dateSuchAs:"有効な日付を入力してください。{date}",dateInFormatMDY:'日付の書式に誤りがあります。YYYY/MM/DD (i.e. "1999/12/31")',email:"メールアドレスに誤りがあります。",url:"URLアドレスに誤りがあります。",currencyDollar:"金額に誤りがあります。",oneRequired:"ひとつ以上入力してください。",errorPrefix:"エラー: ",warningPrefix:"警告: ",noSpace:"スペースは入力できません。",reqChkByNode:"選択されていません。",requiredChk:"この項目は必須です。",reqChkByName:"{label}を選択してください。",match:"{matchName}が入力されている場合必須です。",startDate:"開始日",endDate:"終了日",currentDate:"今日",afterDate:"{label}以降の日付にしてください。",beforeDate:"{label}以前の日付にしてください。",startMonth:"開始月を選択してください。",sameMonth:"日付が同一です。どちらかを変更してください。"});Locale.define("ja-JP","Number",{decimal:".",group:",",currency:{decimals:0,prefix:"\\"}});Locale.define("nl-NL","Date",{months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],months_abbr:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],days_abbr:["zo","ma","di","wo","do","vr","za"],dateOrder:["date","month","year"],shortDate:"%d-%m-%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"e",lessThanMinuteAgo:"minder dan een minuut geleden",minuteAgo:"ongeveer een minuut geleden",minutesAgo:"{delta} minuten geleden",hourAgo:"ongeveer een uur geleden",hoursAgo:"ongeveer {delta} uur geleden",dayAgo:"een dag geleden",daysAgo:"{delta} dagen geleden",weekAgo:"een week geleden",weeksAgo:"{delta} weken geleden",monthAgo:"een maand geleden",monthsAgo:"{delta} maanden geleden",yearAgo:"een jaar geleden",yearsAgo:"{delta} jaar geleden",lessThanMinuteUntil:"over minder dan een minuut",minuteUntil:"over ongeveer een minuut",minutesUntil:"over {delta} minuten",hourUntil:"over ongeveer een uur",hoursUntil:"over {delta} uur",dayUntil:"over ongeveer een dag",daysUntil:"over {delta} dagen",weekUntil:"over een week",weeksUntil:"over {delta} weken",monthUntil:"over een maand",monthsUntil:"over {delta} maanden",yearUntil:"over een jaar",yearsUntil:"over {delta} jaar"});Locale.define("nl-NL","FormValidator",{required:"Dit veld is verplicht.",length:"Vul precies {length} karakters in (je hebt {elLength} karakters ingevoerd).",minLength:"Vul minimaal {minLength} karakters in (je hebt {length} karakters ingevoerd).",maxLength:"Vul niet meer dan {maxLength} karakters in (je hebt {length} karakters ingevoerd).",integer:"Vul een getal in. Getallen met decimalen (bijvoorbeeld 1.25) zijn niet toegestaan.",numeric:'Vul alleen numerieke waarden in (bijvoorbeeld "1" of "1.1" of "-1" of "-1.1").',digits:"Vul alleen nummers en leestekens in (bijvoorbeeld een telefoonnummer met streepjes is toegestaan).",alpha:"Vul alleen letters in (a-z). Spaties en andere karakters zijn niet toegestaan.",alphanum:"Vul alleen letters (a-z) of nummers (0-9) in. Spaties en andere karakters zijn niet toegestaan.",dateSuchAs:"Vul een geldige datum in, zoals {date}",dateInFormatMDY:'Vul een geldige datum, in het formaat MM/DD/YYYY (bijvoorbeeld "12/31/1999")',email:'Vul een geldig e-mailadres in. Bijvoorbeeld "fred@domein.nl".',url:"Vul een geldige URL in, zoals http://www.example.com.",currencyDollar:"Vul een geldig $ bedrag in. Bijvoorbeeld $100.00 .",oneRequired:"Vul iets in bij in ieder geval een van deze velden.",warningPrefix:"Waarschuwing: ",errorPrefix:"Fout: ",noSpace:"Spaties zijn niet toegestaan in dit veld.",reqChkByNode:"Er zijn geen items geselecteerd.",requiredChk:"Dit veld is verplicht.",reqChkByName:"Selecteer een {label}.",match:"Dit veld moet overeen komen met het {matchName} veld",startDate:"de begin datum",endDate:"de eind datum",currentDate:"de huidige datum",afterDate:"De datum moet hetzelfde of na {label} zijn.",beforeDate:"De datum moet hetzelfde of voor {label} zijn.",startMonth:"Selecteer een begin maand",sameMonth:"Deze twee data moeten in dezelfde maand zijn - u moet een van beide aanpassen.",creditcard:"Het ingevulde creditcardnummer is niet geldig. Controleer het nummer en probeer opnieuw. {length} getallen ingevuld."});Locale.define("nl-NL").inherit("EU","Number");Locale.define("no-NO","Date",{months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],months_abbr:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],days_abbr:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],dateOrder:["date","month","year"],shortDate:"%d.%m.%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,lessThanMinuteAgo:"mindre enn et minutt siden",minuteAgo:"omtrent et minutt siden",minutesAgo:"{delta} minutter siden",hourAgo:"omtrent en time siden",hoursAgo:"omtrent {delta} timer siden",dayAgo:"{delta} dag siden",daysAgo:"{delta} dager siden",weekAgo:"en uke siden",weeksAgo:"{delta} uker siden",monthAgo:"en måned siden",monthsAgo:"{delta} måneder siden",yearAgo:"ett år siden",yearsAgo:"{delta} år siden",lessThanMinuteUntil:"mindre enn et minutt til",minuteUntil:"omtrent et minutt til",minutesUntil:"{delta} minutter til",hourUntil:"omtrent en time til",hoursUntil:"omtrent {delta} timer til",dayUntil:"en dag til",daysUntil:"{delta} dager til",weekUntil:"en uke til",weeksUntil:"{delta} uker til",monthUntil:"en måned til",monthsUntil:"{delta} måneder til",yearUntil:"et år til",yearsUntil:"{delta} år til"});Locale.define("no-NO","FormValidator",{required:"Dette feltet er pÃ¥krevd.",minLength:"Vennligst skriv inn minst {minLength} tegn (du skrev {length} tegn).",maxLength:"Vennligst skriv inn maksimalt {maxLength} tegn (du skrev {length} tegn).",integer:"Vennligst skriv inn et tall i dette feltet. Tall med desimaler (for eksempel 1,25) er ikke tillat.",numeric:'Vennligst skriv inn kun numeriske verdier i dette feltet (for eksempel "1", "1.1", "-1" eller "-1.1").',digits:"Vennligst bruk kun nummer og skilletegn i dette feltet.",alpha:"Vennligst bruk kun bokstaver (a-z) i dette feltet. Ingen mellomrom eller andre tegn er tillat.",alphanum:"Vennligst bruk kun bokstaver (a-z) eller nummer (0-9) i dette feltet. Ingen mellomrom eller andre tegn er tillat.",dateSuchAs:"Vennligst skriv inn en gyldig dato, som {date}",dateInFormatMDY:'Vennligst skriv inn en gyldig dato, i formatet MM/DD/YYYY (for eksempel "12/31/1999")',email:'Vennligst skriv inn en gyldig epost-adresse. For eksempel "espen@domene.no".',url:"Vennligst skriv inn en gyldig URL, for eksempel http://www.example.com.",currencyDollar:"Vennligst fyll ut et gyldig $ beløp. For eksempel $100.00 .",oneRequired:"Vennligst fyll ut noe i minst ett av disse feltene.",errorPrefix:"Feil: ",warningPrefix:"Advarsel: "});Locale.define("pl-PL","Date",{months:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],months_abbr:["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru"],days:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],days_abbr:["niedz.","pon.","wt.","śr.","czw.","pt.","sob."],dateOrder:["year","month","date"],shortDate:"%Y-%m-%d",shortTime:"%H:%M",AM:"nad ranem",PM:"po południu",firstDayOfWeek:1,ordinal:function(b){return(b>3&&b<21)?"ty":["ty","szy","gi","ci","ty"][Math.min(b%10,4)]},lessThanMinuteAgo:"mniej niż minute temu",minuteAgo:"około minutę temu",minutesAgo:"{delta} minut temu",hourAgo:"około godzinę temu",hoursAgo:"około {delta} godzin temu",dayAgo:"Wczoraj",daysAgo:"{delta} dni temu",lessThanMinuteUntil:"za niecałą minutę",minuteUntil:"za około minutę",minutesUntil:"za {delta} minut",hourUntil:"za około godzinę",hoursUntil:"za około {delta} godzin",dayUntil:"za 1 dzień",daysUntil:"za {delta} dni"});Locale.define("pl-PL","FormValidator",{required:"To pole jest wymagane.",minLength:"Wymagane jest przynajmniej {minLength} znaków (wpisanych zostało tylko {length}).",maxLength:"Dozwolone jest nie więcej niż {maxLength} znaków (wpisanych zostało {length})",integer:"To pole wymaga liczb całych. Liczby dziesiętne (np. 1.25) są niedozwolone.",numeric:'Prosimy używać tylko numerycznych wartości w tym polu (np. "1", "1.1", "-1" lub "-1.1").',digits:"Prosimy używać liczb oraz zankow punktuacyjnych w typ polu (dla przykładu, przy numerze telefonu myślniki i kropki są dozwolone).",alpha:"Prosimy używać tylko liter (a-z) w tym polu. Spacje oraz inne znaki są niedozwolone.",alphanum:"Prosimy używać tylko liter (a-z) lub liczb (0-9) w tym polu. Spacje oraz inne znaki są niedozwolone.",dateSuchAs:"Prosimy podać prawidłową datę w formacie: {date}",dateInFormatMDY:'Prosimy podać poprawną date w formacie DD.MM.RRRR (i.e. "12.01.2009")',email:'Prosimy podać prawidłowy adres e-mail, np. "jan@domena.pl".',url:"Prosimy podać prawidłowy adres URL, np. http://www.example.com.",currencyDollar:"Prosimy podać prawidłową sumę w PLN. Dla przykładu: 100.00 PLN.",oneRequired:"Prosimy wypełnić chociaż jedno z pól.",errorPrefix:"Błąd: ",warningPrefix:"Uwaga: ",noSpace:"W tym polu nie mogą znajdować się spacje.",reqChkByNode:"Brak zaznaczonych elementów.",requiredChk:"To pole jest wymagane.",reqChkByName:"Prosimy wybrać z {label}.",match:"To pole musi być takie samo jak {matchName}",startDate:"data początkowa",endDate:"data końcowa",currentDate:"aktualna data",afterDate:"Podana data poinna być taka sama lub po {label}.",beforeDate:"Podana data poinna być taka sama lub przed {label}.",startMonth:"Prosimy wybrać początkowy miesiąc.",sameMonth:"Te dwie daty muszą być w zakresie tego samego miesiąca - wymagana jest zmiana któregoś z pól."});Locale.define("pt-PT","Date",{months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],months_abbr:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],days:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],days_abbr:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dateOrder:["date","month","year"],shortDate:"%d-%m-%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"º",lessThanMinuteAgo:"há menos de um minuto",minuteAgo:"há cerca de um minuto",minutesAgo:"há {delta} minutos",hourAgo:"há cerca de uma hora",hoursAgo:"há cerca de {delta} horas",dayAgo:"há um dia",daysAgo:"há {delta} dias",weekAgo:"há uma semana",weeksAgo:"há {delta} semanas",monthAgo:"há um mês",monthsAgo:"há {delta} meses",yearAgo:"há um ano",yearsAgo:"há {delta} anos",lessThanMinuteUntil:"em menos de um minuto",minuteUntil:"em um minuto",minutesUntil:"em {delta} minutos",hourUntil:"em uma hora",hoursUntil:"em {delta} horas",dayUntil:"em um dia",daysUntil:"em {delta} dias",weekUntil:"em uma semana",weeksUntil:"em {delta} semanas",monthUntil:"em um mês",monthsUntil:"em {delta} meses",yearUntil:"em um ano",yearsUntil:"em {delta} anos"});Locale.define("pt-BR","Date",{shortDate:"%d/%m/%Y"}).inherit("pt-PT","Date");Locale.define("pt-BR","FormValidator",{required:"Este campo é obrigatório.",minLength:"Digite pelo menos {minLength} caracteres (tamanho atual: {length}).",maxLength:"Não digite mais de {maxLength} caracteres (tamanho atual: {length}).",integer:"Por favor digite apenas um número inteiro neste campo. Não são permitidos números decimais (por exemplo, 1,25).",numeric:'Por favor digite apenas valores numéricos neste campo (por exemplo, "1" ou "1.1" ou "-1" ou "-1,1").',digits:"Por favor use apenas números e pontuação neste campo (por exemplo, um número de telefone com traços ou pontos é permitido).",alpha:"Por favor use somente letras (a-z). Espaço e outros caracteres não são permitidos.",alphanum:"Use somente letras (a-z) ou números (0-9) neste campo. Espaço e outros caracteres não são permitidos.",dateSuchAs:"Digite uma data válida, como {date}",dateInFormatMDY:'Digite uma data válida, como DD/MM/YYYY (por exemplo, "31/12/1999")',email:'Digite um endereço de email válido. Por exemplo "nome@dominio.com".',url:"Digite uma URL válida. Exemplo: http://www.example.com.",currencyDollar:"Digite um valor em dinheiro válido. Exemplo: R$100,00 .",oneRequired:"Digite algo para pelo menos um desses campos.",errorPrefix:"Erro: ",warningPrefix:"Aviso: ",noSpace:"Não é possível digitar espaços neste campo.",reqChkByNode:"Não foi selecionado nenhum item.",requiredChk:"Este campo é obrigatório.",reqChkByName:"Por favor digite um {label}.",match:"Este campo deve ser igual ao campo {matchName}.",startDate:"a data inicial",endDate:"a data final",currentDate:"a data atual",afterDate:"A data deve ser igual ou posterior a {label}.",beforeDate:"A data deve ser igual ou anterior a {label}.",startMonth:"Por favor selecione uma data inicial.",sameMonth:"Estas duas datas devem ter o mesmo mês - você deve modificar uma das duas.",creditcard:"O número do cartão de crédito informado é inválido. Por favor verifique o valor e tente novamente. {length} números informados."});Locale.define("pt-BR","Number",{decimal:",",group:".",currency:{prefix:"R$ "}});Locale.define("pt-PT","FormValidator",{required:"Este campo é necessário.",minLength:"Digite pelo menos{minLength} caracteres (comprimento {length} caracteres).",maxLength:"Não insira mais de {maxLength} caracteres (comprimento {length} caracteres).",integer:"Digite um número inteiro neste domínio. Com números decimais (por exemplo, 1,25), não são permitidas.",numeric:'Digite apenas valores numéricos neste domínio (p.ex., "1" ou "1.1" ou "-1" ou "-1,1").',digits:"Por favor, use números e pontuação apenas neste campo (p.ex., um número de telefone com traços ou pontos é permitida).",alpha:"Por favor use somente letras (a-z), com nesta área. Não utilize espaços nem outros caracteres são permitidos.",alphanum:"Use somente letras (a-z) ou números (0-9) neste campo. Não utilize espaços nem outros caracteres são permitidos.",dateSuchAs:"Digite uma data válida, como {date}",dateInFormatMDY:'Digite uma data válida, como DD/MM/YYYY (p.ex. "31/12/1999")',email:'Digite um endereço de email válido. Por exemplo "fred@domain.com".',url:"Digite uma URL válida, como http://www.example.com.",currencyDollar:"Digite um valor válido $. Por exemplo $ 100,00. ",oneRequired:"Digite algo para pelo menos um desses insumos.",errorPrefix:"Erro: ",warningPrefix:"Aviso: "});(function(){var b=function(i,l,m,j,a){var n=i%10,k=i%100;if(n==1&&k!=11){return l}else{if((n==2||n==3||n==4)&&!(k==12||k==13||k==14)){return m}else{if(n==0||(n==5||n==6||n==7||n==8||n==9)||(k==11||k==12||k==13||k==14)){return j}else{return a}}}};Locale.define("ru-RU","Date",{months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],months_abbr:["янв","февр","март","апр","май","июнь","июль","авг","сент","окт","нояб","дек"],days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],days_abbr:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],dateOrder:["date","month","year"],shortDate:"%d.%m.%Y",shortTime:"%H:%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"меньше минуты назад",minuteAgo:"минуту назад",minutesAgo:function(a){return"{delta} "+b(a,"минуту","минуты","минут")+" назад"},hourAgo:"час назад",hoursAgo:function(a){return"{delta} "+b(a,"час","часа","часов")+" назад"},dayAgo:"вчера",daysAgo:function(a){return"{delta} "+b(a,"день","дня","дней")+" назад"},weekAgo:"неделю назад",weeksAgo:function(a){return"{delta} "+b(a,"неделя","недели","недель")+" назад"},monthAgo:"месяц назад",monthsAgo:function(a){return"{delta} "+b(a,"месяц","месяца","месяцев")+" назад"},yearAgo:"год назад",yearsAgo:function(a){return"{delta} "+b(a,"год","года","лет")+" назад"},lessThanMinuteUntil:"меньше чем через минуту",minuteUntil:"через минуту",minutesUntil:function(a){return"через {delta} "+b(a,"минуту","минуты","минут")+""},hourUntil:"через час",hoursUntil:function(a){return"через {delta} "+b(a,"час","часа","часов")+""},dayUntil:"завтра",daysUntil:function(a){return"через {delta} "+b(a,"день","дня","дней")+""},weekUntil:"через неделю",weeksUntil:function(a){return"через {delta} "+b(a,"неделю","недели","недель")+""},monthUntil:"через месяц",monthsUntil:function(a){return"через {delta} "+b(a,"месяц","месяца","месяцев")+""},yearUntil:"через",yearsUntil:function(a){return"через {delta} "+b(a,"год","года","лет")+""}})})();Locale.define("ru-RU","FormValidator",{required:"Это поле обязательно к заполнению.",minLength:"Пожалуйста, введите хотя бы {minLength} символов (Вы ввели {length}).",maxLength:"Пожалуйста, введите не больше {maxLength} символов (Вы ввели {length}).",integer:"Пожалуйста, введите в это поле число. Дробные числа (например 1.25) тут не разрешены.",numeric:'Пожалуйста, введите в это поле число (например "1" или "1.1", или "-1", или "-1.1").',digits:"В этом поле Вы можете использовать только цифры и знаки пунктуации (например, телефонный номер со знаками дефиса или с точками).",alpha:"В этом поле можно использовать только латинские буквы (a-z). Пробелы и другие символы запрещены.",alphanum:"В этом поле можно использовать только латинские буквы (a-z) и цифры (0-9). Пробелы и другие символы запрещены.",dateSuchAs:"Пожалуйста, введите корректную дату {date}",dateInFormatMDY:'Пожалуйста, введите дату в формате ММ/ДД/ГГГГ (например "12/31/1999")',email:'Пожалуйста, введите корректный емейл-адрес. Для примера "fred@domain.com".',url:"Пожалуйста, введите правильную ссылку вида http://www.example.com.",currencyDollar:"Пожалуйста, введите сумму в долларах. Например: $100.00 .",oneRequired:"Пожалуйста, выберите хоть что-нибудь в одном из этих полей.",errorPrefix:"Ошибка: ",warningPrefix:"Внимание: "});(function(){var b=function(f,g,h,a){if(f==1){return g}else{if(f==2||f==3||f==4){return h}else{return a}}};Locale.define("sk-SK","Date",{months:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"],months_abbr:["januára","februára","marca","apríla","mája","júna","júla","augusta","septembra","októbra","novembra","decembra"],days:["Nedele","Pondelí","Úterý","Streda","Čtvrtek","Pátek","Sobota"],days_abbr:["ne","po","ut","st","št","pi","so"],dateOrder:["date","month","year"],shortDate:"%d.%m.%Y",shortTime:"%H:%M",AM:"dop.",PM:"pop.",firstDayOfWeek:1,ordinal:".",lessThanMinuteAgo:"pred chvíľou",minuteAgo:"približne pred minútou",minutesAgo:function(a){return"pred {delta} "+b(a,"minútou","minútami","minútami")},hourAgo:"približne pred hodinou",hoursAgo:function(a){return"pred {delta} "+b(a,"hodinou","hodinami","hodinami")},dayAgo:"pred dňom",daysAgo:function(a){return"pred {delta} "+b(a,"dňom","dňami","dňami")},weekAgo:"pred týždňom",weeksAgo:function(a){return"pred {delta} "+b(a,"týždňom","týždňami","týždňami")},monthAgo:"pred mesiacom",monthsAgo:function(a){return"pred {delta} "+b(a,"mesiacom","mesiacmi","mesiacmi")},yearAgo:"pred rokom",yearsAgo:function(a){return"pred {delta} "+b(a,"rokom","rokmi","rokmi")},lessThanMinuteUntil:"o chvíľu",minuteUntil:"približne o minútu",minutesUntil:function(a){return"o {delta} "+b(a,"minútu","minúty","minúty")},hourUntil:"približne o hodinu",hoursUntil:function(a){return"o {delta} "+b(a,"hodinu","hodiny","hodín")},dayUntil:"o deň",daysUntil:function(a){return"o {delta} "+b(a,"deň","dni","dní")},weekUntil:"o týždeň",weeksUntil:function(a){return"o {delta} "+b(a,"týždeň","týždne","týždňov")},monthUntil:"o mesiac",monthsUntil:function(a){return"o {delta} "+b(a,"mesiac","mesiace","mesiacov")},yearUntil:"o rok",yearsUntil:function(a){return"o {delta} "+b(a,"rok","roky","rokov")}})})();Locale.define("sk-SK","FormValidator",{required:"Táto položka je povinná.",minLength:"Zadajte prosím aspoň {minLength} znakov (momentálne {length} znakov).",maxLength:"Zadajte prosím menej ako {maxLength} znakov (momentálne {length} znakov).",integer:"Zadajte prosím celé číslo. Desetinné čísla (napr. 1.25) nie sú povolené.",numeric:"Zadajte len číselné hodnoty (t.j. „1“ alebo „1.1“ alebo „-1“ alebo „-1.1“).",digits:"Zadajte prosím len čísla a interpunkčné znamienka (napríklad telefónne číslo s pomlčkami albo bodkami je povolené).",alpha:"Zadajte prosím len písmená (a-z). Medzery alebo iné znaky nie sú povolené.",alphanum:"Zadajte prosím len písmená (a-z) alebo číslice (0-9). Medzery alebo iné znaky nie sú povolené.",dateSuchAs:"Zadajte prosím platný dátum v tvare {date}",dateInFormatMDY:"Zadajte prosím platný datum v tvare MM / DD / RRRR (t.j. „12/31/1999“)",email:"Zadajte prosím platnú emailovú adresu. Napríklad „fred@domain.com“.",url:"Zadajte prosím platnoú adresu URL v tvare http://www.example.com.",currencyDollar:"Zadajte prosím platnú čiastku. Napríklad $100.00.",oneRequired:"Zadajte prosím aspoň jednu hodnotu z týchto položiek.",errorPrefix:"Chyba: ",warningPrefix:"Upozornenie: ",noSpace:"V tejto položle nie sú povolené medzery",reqChkByNode:"Nie sú vybrané žiadne položky.",requiredChk:"Táto položka je povinná.",reqChkByName:"Prosím vyberte {label}.",match:"Táto položka sa musí zhodovať s položkou {matchName}",startDate:"dátum začiatku",endDate:"dátum ukončenia",currendDate:"aktuálny dátum",afterDate:"Dátum by mal býť rovnaký alebo väčší ako {label}.",beforeDate:"Dátum by mal byť rovnaký alebo menší ako {label}.",startMonth:"Vyberte počiatočný mesiac.",sameMonth:"Tieto dva dátumy musia býť v rovnakom mesiaci - zmeňte jeden z nich.",creditcard:"Zadané číslo kreditnej karty je neplatné. Prosím, opravte ho. Bolo zadaných {length} číslic."});(function(){var b=function(g,i,j,h,a){return(g>=1&&g<=3)?arguments[g]:a};Locale.define("sl-SI","Date",{months:["januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december"],months_abbr:["jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec"],days:["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],days_abbr:["ned","pon","tor","sre","čet","pet","sob"],dateOrder:["date","month","year"],shortDate:"%d.%m.%Y",shortTime:"%H.%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:".",lessThanMinuteAgo:"manj kot minuto nazaj",minuteAgo:"minuto nazaj",minutesAgo:function(a){return"{delta} "+b(a,"minuto","minuti","minute","minut")+" nazaj"},hourAgo:"uro nazaj",hoursAgo:function(a){return"{delta} "+b(a,"uro","uri","ure","ur")+" nazaj"},dayAgo:"dan nazaj",daysAgo:function(a){return"{delta} "+b(a,"dan","dneva","dni","dni")+" nazaj"},weekAgo:"teden nazaj",weeksAgo:function(a){return"{delta} "+b(a,"teden","tedna","tedne","tednov")+" nazaj"},monthAgo:"mesec nazaj",monthsAgo:function(a){return"{delta} "+b(a,"mesec","meseca","mesece","mesecov")+" nazaj"},yearthAgo:"leto nazaj",yearsAgo:function(a){return"{delta} "+b(a,"leto","leti","leta","let")+" nazaj"},lessThanMinuteUntil:"še manj kot minuto",minuteUntil:"še minuta",minutesUntil:function(a){return"še {delta} "+b(a,"minuta","minuti","minute","minut")},hourUntil:"še ura",hoursUntil:function(a){return"še {delta} "+b(a,"ura","uri","ure","ur")},dayUntil:"še dan",daysUntil:function(a){return"še {delta} "+b(a,"dan","dneva","dnevi","dni")},weekUntil:"še tedn",weeksUntil:function(a){return"še {delta} "+b(a,"teden","tedna","tedni","tednov")},monthUntil:"še mesec",monthsUntil:function(a){return"še {delta} "+b(a,"mesec","meseca","meseci","mesecov")},yearUntil:"še leto",yearsUntil:function(a){return"še {delta} "+b(a,"leto","leti","leta","let")}})})();Locale.define("sl-SI","FormValidator",{required:"To polje je obvezno",minLength:"Prosim, vnesite vsaj {minLength} znakov (vnesli ste {length} znakov).",maxLength:"Prosim, ne vnesite več kot {maxLength} znakov (vnesli ste {length} znakov).",integer:"Prosim, vnesite celo število. Decimalna števila (kot 1,25) niso dovoljena.",numeric:'Prosim, vnesite samo numerične vrednosti (kot "1" ali "1.1" ali "-1" ali "-1.1").',digits:"Prosim, uporabite številke in ločila le na tem polju (na primer, dovoljena je telefonska številka z pomišlaji ali pikami).",alpha:"Prosim, uporabite le črke v tem plju. Presledki in drugi znaki niso dovoljeni.",alphanum:"Prosim, uporabite samo črke ali številke v tem polju. Presledki in drugi znaki niso dovoljeni.",dateSuchAs:"Prosim, vnesite pravilen datum kot {date}",dateInFormatMDY:'Prosim, vnesite pravilen datum kot MM.DD.YYYY (primer "12.31.1999")',email:'Prosim, vnesite pravilen email naslov. Na primer "fred@domain.com".',url:"Prosim, vnesite pravilen URL kot http://www.example.com.",currencyDollar:"Prosim, vnesit epravilno vrednost €. Primer 100,00€ .",oneRequired:"Prosimo, vnesite nekaj za vsaj eno izmed teh polj.",errorPrefix:"Napaka: ",warningPrefix:"Opozorilo: ",noSpace:"To vnosno polje ne dopušča presledkov.",reqChkByNode:"Nič niste izbrali.",requiredChk:"To polje je obvezno",reqChkByName:"Prosim, izberite {label}.",match:"To polje se mora ujemati z poljem {matchName}",startDate:"datum začetka",endDate:"datum konca",currentDate:"trenuten datum",afterDate:"Datum bi moral biti isti ali po {label}.",beforeDate:"Datum bi moral biti isti ali pred {label}.",startMonth:"Prosim, vnesite začetni datum",sameMonth:"Ta dva datuma morata biti v istem mesecu - premeniti morate eno ali drugo.",creditcard:"Številka kreditne kartice ni pravilna. Preverite številko ali poskusite še enkrat. Vnešenih {length} znakov."});Locale.define("sv-SE","Date",{months:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],months_abbr:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],days:["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],days_abbr:["sön","mån","tis","ons","tor","fre","lör"],dateOrder:["year","month","date"],shortDate:"%Y-%m-%d",shortTime:"%H:%M",AM:"",PM:"",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"mindre än en minut sedan",minuteAgo:"ungefär en minut sedan",minutesAgo:"{delta} minuter sedan",hourAgo:"ungefär en timme sedan",hoursAgo:"ungefär {delta} timmar sedan",dayAgo:"1 dag sedan",daysAgo:"{delta} dagar sedan",lessThanMinuteUntil:"mindre än en minut sedan",minuteUntil:"ungefär en minut sedan",minutesUntil:"{delta} minuter sedan",hourUntil:"ungefär en timme sedan",hoursUntil:"ungefär {delta} timmar sedan",dayUntil:"1 dag sedan",daysUntil:"{delta} dagar sedan"});Locale.define("sv-SE","FormValidator",{required:"Fältet är obligatoriskt.",minLength:"Ange minst {minLength} tecken (du angav {length} tecken).",maxLength:"Ange högst {maxLength} tecken (du angav {length} tecken). ",integer:"Ange ett heltal i fältet. Tal med decimaler (t.ex. 1,25) är inte tillåtna.",numeric:'Ange endast numeriska värden i detta fält (t.ex. "1" eller "1.1" eller "-1" eller "-1,1").',digits:"Använd endast siffror och skiljetecken i detta fält (till exempel ett telefonnummer med bindestreck tillåtet).",alpha:"Använd endast bokstäver (a-ö) i detta fält. Inga mellanslag eller andra tecken är tillåtna.",alphanum:"Använd endast bokstäver (a-ö) och siffror (0-9) i detta fält. Inga mellanslag eller andra tecken är tillåtna.",dateSuchAs:"Ange ett giltigt datum som t.ex. {date}",dateInFormatMDY:'Ange ett giltigt datum som t.ex. YYYY-MM-DD (i.e. "1999-12-31")',email:'Ange en giltig e-postadress. Till exempel "erik@domain.com".',url:"Ange en giltig webbadress som http://www.example.com.",currencyDollar:"Ange en giltig belopp. Exempelvis 100,00.",oneRequired:"Vänligen ange minst ett av dessa alternativ.",errorPrefix:"Fel: ",warningPrefix:"Varning: ",noSpace:"Det får inte finnas några mellanslag i detta fält.",reqChkByNode:"Inga objekt är valda.",requiredChk:"Detta är ett obligatoriskt fält.",reqChkByName:"Välj en {label}.",match:"Detta fält måste matcha {matchName}",startDate:"startdatumet",endDate:"slutdatum",currentDate:"dagens datum",afterDate:"Datumet bör vara samma eller senare än {label}.",beforeDate:"Datumet bör vara samma eller tidigare än {label}.",startMonth:"Välj en start månad",sameMonth:"Dessa två datum måste vara i samma månad - du måste ändra det ena eller det andra."});Locale.define("sv-SE","Number",{currency:{prefix:"SEK "}}).inherit("EU","Number");Locale.define("tr-TR","Date",{months:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],months_abbr:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],days:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],days_abbr:["Pa","Pzt","Sa","Ça","Pe","Cu","Cmt"],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H.%M",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"bir dakikadan önce",minuteAgo:"yaklaşık bir dakika önce",minutesAgo:"{delta} dakika önce",hourAgo:"bir saat kadar önce",hoursAgo:"{delta} saat kadar önce",dayAgo:"bir gün önce",daysAgo:"{delta} gün önce",weekAgo:"bir hafta önce",weeksAgo:"{delta} hafta önce",monthAgo:"bir ay önce",monthsAgo:"{delta} ay önce",yearAgo:"bir yıl önce",yearsAgo:"{delta} yıl önce",lessThanMinuteUntil:"bir dakikadan az sonra",minuteUntil:"bir dakika kadar sonra",minutesUntil:"{delta} dakika sonra",hourUntil:"bir saat kadar sonra",hoursUntil:"{delta} saat kadar sonra",dayUntil:"bir gün sonra",daysUntil:"{delta} gün sonra",weekUntil:"bir hafta sonra",weeksUntil:"{delta} hafta sonra",monthUntil:"bir ay sonra",monthsUntil:"{delta} ay sonra",yearUntil:"bir yıl sonra",yearsUntil:"{delta} yıl sonra"});Locale.define("tr-TR","FormValidator",{required:"Bu alan zorunlu.",minLength:"Lütfen en az {minLength} karakter girin (siz {length} karakter girdiniz).",maxLength:"Lütfen en fazla {maxLength} karakter girin (siz {length} karakter girdiniz).",integer:"Lütfen bu alana sadece tamsayı girin. Ondalıklı sayılar (ör: 1.25) kullanılamaz.",numeric:'Lütfen bu alana sadece sayısal değer girin (ör: "1", "1.1", "-1" ya da "-1.1").',digits:"Lütfen bu alana sadece sayısal değer ve noktalama işareti girin (örneğin, nokta ve tire içeren bir telefon numarası kullanılabilir).",alpha:"Lütfen bu alanda yalnızca harf kullanın. Boşluk ve diğer karakterler kullanılamaz.",alphanum:"Lütfen bu alanda sadece harf ve rakam kullanın. Boşluk ve diğer karakterler kullanılamaz.",dateSuchAs:"Lütfen geçerli bir tarih girin (Ör: {date})",dateInFormatMDY:'Lütfen geçerli bir tarih girin (GG/AA/YYYY, ör: "31/12/1999")',email:'Lütfen geçerli bir email adresi girin. Ör: "kemal@etikan.com".',url:"Lütfen geçerli bir URL girin. Ör: http://www.example.com.",currencyDollar:"Lütfen geçerli bir TL miktarı girin. Ör: 100,00 TL .",oneRequired:"Lütfen en az bir tanesini doldurun.",errorPrefix:"Hata: ",warningPrefix:"Uyarı: ",noSpace:"Bu alanda boşluk kullanılamaz.",reqChkByNode:"Hiçbir öğe seçilmemiş.",requiredChk:"Bu alan zorunlu.",reqChkByName:"Lütfen bir {label} girin.",match:"Bu alan, {matchName} alanıyla uyuşmalı",startDate:"başlangıç tarihi",endDate:"bitiş tarihi",currentDate:"bugünün tarihi",afterDate:"Tarih, {label} tarihiyle aynı gün ya da ondan sonra olmalıdır.",beforeDate:"Tarih, {label} tarihiyle aynı gün ya da ondan önce olmalıdır.",startMonth:"Lütfen bir başlangıç ayı seçin",sameMonth:"Bu iki tarih aynı ayda olmalı - bir tanesini değiştirmeniz gerekiyor.",creditcard:"Girdiğiniz kredi kartı numarası geçersiz. Lütfen kontrol edip tekrar deneyin. {length} hane girildi."});Locale.define("tr-TR","Number",{currency:{decimals:0,suffix:" TL"}}).inherit("EU","Number");(function(){var b=function(d,o,p,k,a){var l=(d/10).toInt(),m=d%10,n=(d/100).toInt();if(l==1&&d>10){return k}if(m==1){return o}if(m>0&&m<5){return p}return k};Locale.define("uk-UA","Date",{months:["Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],months_abbr:["Січ","Лют","Бер","Квіт","Трав","Черв","Лип","Серп","Вер","Жовт","Лист","Груд"],days:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота"],days_abbr:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M",AM:"до полудня",PM:"по полудню",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"меньше хвилини тому",minuteAgo:"хвилину тому",minutesAgo:function(a){return"{delta} "+b(a,"хвилину","хвилини","хвилин")+" тому"},hourAgo:"годину тому",hoursAgo:function(a){return"{delta} "+b(a,"годину","години","годин")+" тому"},dayAgo:"вчора",daysAgo:function(a){return"{delta} "+b(a,"день","дня","днів")+" тому"},weekAgo:"тиждень тому",weeksAgo:function(a){return"{delta} "+b(a,"тиждень","тижні","тижнів")+" тому"},monthAgo:"місяць тому",monthsAgo:function(a){return"{delta} "+b(a,"місяць","місяці","місяців")+" тому"},yearAgo:"рік тому",yearsAgo:function(a){return"{delta} "+b(a,"рік","роки","років")+" тому"},lessThanMinuteUntil:"за мить",minuteUntil:"через хвилину",minutesUntil:function(a){return"через {delta} "+b(a,"хвилину","хвилини","хвилин")},hourUntil:"через годину",hoursUntil:function(a){return"через {delta} "+b(a,"годину","години","годин")},dayUntil:"завтра",daysUntil:function(a){return"через {delta} "+b(a,"день","дня","днів")},weekUntil:"через тиждень",weeksUntil:function(a){return"через {delta} "+b(a,"тиждень","тижні","тижнів")},monthUntil:"через місяць",monthesUntil:function(a){return"через {delta} "+b(a,"місяць","місяці","місяців")},yearUntil:"через рік",yearsUntil:function(a){return"через {delta} "+b(a,"рік","роки","років")}})})();Locale.define("uk-UA","FormValidator",{required:"Це поле повинне бути заповненим.",minLength:"Введіть хоча б {minLength} символів (Ви ввели {length}).",maxLength:"Кількість символів не може бути більше {maxLength} (Ви ввели {length}).",integer:"Введіть в це поле число. Дробові числа (наприклад 1.25) не дозволені.",numeric:'Введіть в це поле число (наприклад "1" або "1.1", або "-1", або "-1.1").',digits:"В цьому полі ви можете використовувати лише цифри і знаки пунктіації (наприклад, телефонний номер з знаками дефізу або з крапками).",alpha:"В цьому полі можна використовувати лише латинські літери (a-z). Пробіли і інші символи заборонені.",alphanum:"В цьому полі можна використовувати лише латинські літери (a-z) і цифри (0-9). Пробіли і інші символи заборонені.",dateSuchAs:"Введіть коректну дату {date}.",dateInFormatMDY:'Введіть дату в форматі ММ/ДД/РРРР (наприклад "12/31/2009").',email:'Введіть коректну адресу електронної пошти (наприклад "name@domain.com").',url:"Введіть коректне інтернет-посилання (наприклад http://www.example.com).",currencyDollar:'Введіть суму в доларах (наприклад "$100.00").',oneRequired:"Заповніть одне з полів.",errorPrefix:"Помилка: ",warningPrefix:"Увага: ",noSpace:"Пробіли заборонені.",reqChkByNode:"Не відмічено жодного варіанту.",requiredChk:"Це поле повинне бути віміченим.",reqChkByName:"Будь ласка, відмітьте {label}.",match:"Це поле повинно відповідати {matchName}",startDate:"початкова дата",endDate:"кінцева дата",currentDate:"сьогоднішня дата",afterDate:"Ця дата повинна бути такою ж, або пізнішою за {label}.",beforeDate:"Ця дата повинна бути такою ж, або ранішою за {label}.",startMonth:"Будь ласка, виберіть початковий місяць",sameMonth:"Ці дати повинні відноситись одного і того ж місяця. Будь ласка, змініть одну з них.",creditcard:"Номер кредитної карти введений неправильно. Будь ласка, перевірте його. Введено {length} символів."});Locale.define("zh-CHS","Date",{months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],months_abbr:["一","二","三","四","五","六","七","八","九","十","十一","十二"],days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],days_abbr:["日","一","二","三","四","五","六"],dateOrder:["year","month","date"],shortDate:"%Y-%m-%d",shortTime:"%I:%M%p",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"不到1分钟前",minuteAgo:"大约1分钟前",minutesAgo:"{delta}分钟之前",hourAgo:"大约1小时前",hoursAgo:"大约{delta}小时前",dayAgo:"1天前",daysAgo:"{delta}天前",weekAgo:"1星期前",weeksAgo:"{delta}星期前",monthAgo:"1个月前",monthsAgo:"{delta}个月前",yearAgo:"1年前",yearsAgo:"{delta}年前",lessThanMinuteUntil:"从现在开始不到1分钟",minuteUntil:"从现在开始約1分钟",minutesUntil:"从现在开始约{delta}分钟",hourUntil:"从现在开始1小时",hoursUntil:"从现在开始约{delta}小时",dayUntil:"从现在开始1天",daysUntil:"从现在开始{delta}天",weekUntil:"从现在开始1星期",weeksUntil:"从现在开始{delta}星期",monthUntil:"从现在开始一个月",monthsUntil:"从现在开始{delta}个月",yearUntil:"从现在开始1年",yearsUntil:"从现在开始{delta}年"});Locale.define("zh-CHT","Date",{months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],months_abbr:["一","二","三","四","五","六","七","八","九","十","十一","十二"],days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],days_abbr:["日","一","二","三","四","五","六"],dateOrder:["year","month","date"],shortDate:"%Y-%m-%d",shortTime:"%I:%M%p",AM:"AM",PM:"PM",firstDayOfWeek:1,ordinal:"",lessThanMinuteAgo:"不到1分鐘前",minuteAgo:"大約1分鐘前",minutesAgo:"{delta}分鐘之前",hourAgo:"大約1小時前",hoursAgo:"大約{delta}小時前",dayAgo:"1天前",daysAgo:"{delta}天前",weekAgo:"1星期前",weeksAgo:"{delta}星期前",monthAgo:"1个月前",monthsAgo:"{delta}个月前",yearAgo:"1年前",yearsAgo:"{delta}年前",lessThanMinuteUntil:"從現在開始不到1分鐘",minuteUntil:"從現在開始約1分鐘",minutesUntil:"從現在開始約{delta}分鐘",hourUntil:"從現在開始1小時",hoursUntil:"從現在開始約{delta}小時",dayUntil:"從現在開始1天",daysUntil:"從現在開始{delta}天",weekUntil:"從現在開始1星期",weeksUntil:"從現在開始{delta}星期",monthUntil:"從現在開始一個月",monthsUntil:"從現在開始{delta}個月",yearUntil:"從現在開始1年",yearsUntil:"從現在開始{delta}年"});Locale.define("zh-CHS","FormValidator",{required:"此项必填。",minLength:"请至少输入 {minLength} 个字符 (已输入 {length} 个)。",maxLength:"最多只能输入 {maxLength} 个字符 (已输入 {length} 个)。",integer:'请输入一个整数,不能包含小数点。例如:"1", "200"。',numeric:'请输入一个数字,例如:"1", "1.1", "-1", "-1.1"。',digits:"请输入由数字和标点符号组成的内容。例如电话号码。",alpha:"请输入 A-Z 的 26 个字母,不能包含空格或任何其他字符。",alphanum:"请输入 A-Z 的 26 个字母或 0-9 的 10 个数字,不能包含空格或任何其他字符。",dateSuchAs:"请输入合法的日期格式,如:{date}。",dateInFormatMDY:'请输入合法的日期格式,例如:YYYY-MM-DD ("2010-12-31")。',email:'请输入合法的电子信箱地址,例如:"fred@domain.com"。',url:"请输入合法的 Url 地址,例如:http://www.example.com。",currencyDollar:"请输入合法的货币符号,例如:¥100.0",oneRequired:"请至少选择一项。",errorPrefix:"错误:",warningPrefix:"警告:",noSpace:"不能包含空格。",reqChkByNode:"未选择任何内容。",requiredChk:"此项必填。",reqChkByName:"请选择 {label}.",match:"必须与{matchName}相匹配",startDate:"起始日期",endDate:"结束日期",currentDate:"当前日期",afterDate:"日期必须等于或晚于 {label}.",beforeDate:"日期必须早于或等于 {label}.",startMonth:"请选择起始月份",sameMonth:"您必须修改两个日期中的一个,以确保它们在同一月份。",creditcard:"您输入的信用卡号码不正确。当前已输入{length}个字符。"});Locale.define("zh-CHT","FormValidator",{required:"此項必填。 ",minLength:"請至少輸入{minLength} 個字符(已輸入{length} 個)。 ",maxLength:"最多只能輸入{maxLength} 個字符(已輸入{length} 個)。 ",integer:'請輸入一個整數,不能包含小數點。例如:"1", "200"。 ',numeric:'請輸入一個數字,例如:"1", "1.1", "-1", "-1.1"。 ',digits:"請輸入由數字和標點符號組成的內容。例如電話號碼。 ",alpha:"請輸入AZ 的26 個字母,不能包含空格或任何其他字符。 ",alphanum:"請輸入AZ 的26 個字母或0-9 的10 個數字,不能包含空格或任何其他字符。 ",dateSuchAs:"請輸入合法的日期格式,如:{date}。 ",dateInFormatMDY:'請輸入合法的日期格式,例如:YYYY-MM-DD ("2010-12-31")。 ',email:'請輸入合法的電子信箱地址,例如:"fred@domain.com"。 ',url:"請輸入合法的Url 地址,例如:http://www.example.com。 ",currencyDollar:"請輸入合法的貨幣符號,例如:¥100.0",oneRequired:"請至少選擇一項。 ",errorPrefix:"錯誤:",warningPrefix:"警告:",noSpace:"不能包含空格。 ",reqChkByNode:"未選擇任何內容。 ",requiredChk:"此項必填。 ",reqChkByName:"請選擇 {label}.",match:"必須與{matchName}相匹配",startDate:"起始日期",endDate:"結束日期",currentDate:"當前日期",afterDate:"日期必須等於或晚於{label}.",beforeDate:"日期必須早於或等於{label}.",startMonth:"請選擇起始月份",sameMonth:"您必須修改兩個日期中的一個,以確保它們在同一月份。 ",creditcard:"您輸入的信用卡號碼不正確。當前已輸入{length}個字符。 "});Form.Validator.add("validate-currency-yuan",{errorMsg:function(){return Form.Validator.getMsg("currencyYuan")},test:function(b){return Form.Validator.getValidator("IsEmpty").test(b)||(/^¥?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(b.get("value"))}});Locale.define("zh-CHS","Number",{currency:{prefix:"¥ "}}).inherit("en-US","Number");Locale.define("zh-CHT").inherit("zh-CHS","Number");Locale.define("el-GR","FormValidator",{required:"Αυτό το πεδίο είναι απαραίτητο.",length:"Παρακαλούμε, εισάγετε {length} χαρακτήρες (έχετε ήδη εισάγει {elLength} χαρακτήρες).",minLength:"Παρακαλούμε, εισάγετε τουλάχιστον {minLength} χαρακτήρες (έχετε ήδη εισάγε {length} χαρακτήρες).",maxlength:"Παρακαλούμε, εισάγετε εώς {maxlength} χαρακτήρες (έχετε ήδη εισάγε {length} χαρακτήρες).",integer:"Παρακαλούμε, εισάγετε έναν ακέραιο αριθμό σε αυτό το πεδίο. Οι αριθμοί με δεκαδικά ψηφία (π.χ. 1.25) δεν επιτρέπονται.",numeric:'Παρακαλούμε, εισάγετε μόνο αριθμητικές τιμές σε αυτό το πεδίο (π.χ." 1 " ή " 1.1 " ή " -1 " ή " -1.1 " ).',digits:"Παρακαλούμε, χρησιμοποιήστε μόνο αριθμούς και σημεία στίξης σε αυτόν τον τομέα (π.χ. επιτρέπεται αριθμός τηλεφώνου με παύλες ή τελείες).",alpha:"Παρακαλούμε, χρησιμοποιήστε μόνο γράμματα (a-z) σε αυτό το πεδίο. Δεν επιτρέπονται κενά ή άλλοι χαρακτήρες.",alphanum:"Παρακαλούμε, χρησιμοποιήστε μόνο γράμματα (a-z) ή αριθμούς (0-9) σε αυτόν τον τομέα. Δεν επιτρέπονται κενά ή άλλοι χαρακτήρες.",dateSuchAs:"Παρακαλούμε, εισάγετε μια έγκυρη ημερομηνία, όπως {date}",dateInFormatMDY:'Παρακαλώ εισάγετε μια έγκυρη ημερομηνία, όπως ΜΜ/ΗΗ/ΕΕΕΕ (π.χ. "12/31/1999").',email:'Παρακαλούμε, εισάγετε μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου (π.χ. "fred@domain.com").',url:"Παρακαλούμε, εισάγετε μια έγκυρη URL διεύθυνση, όπως http://www.example.com",currencyDollar:"Παρακαλούμε, εισάγετε ένα έγκυρο ποσό σε δολλάρια (π.χ. $100.00).",oneRequired:"Παρακαλούμε, εισάγετε κάτι για τουλάχιστον ένα από αυτά τα πεδία.",errorPrefix:"Σφάλμα: ",warningPrefix:"Προσοχή: ",noSpace:"Δεν επιτρέπονται τα κενά σε αυτό το πεδίο.",reqChkByNode:"Δεν έχει επιλεγεί κάποιο αντικείμενο",requiredChk:"Αυτό το πεδίο είναι απαραίτητο.",reqChkByName:"Παρακαλούμε, επιλέξτε μια ετικέτα {label}.",match:"Αυτό το πεδίο πρέπει να ταιριάζει με το πεδίο {matchName}.",startDate:"η ημερομηνία έναρξης",endDate:"η ημερομηνία λήξης",currentDate:"η τρέχουσα ημερομηνία",afterDate:"Η ημερομηνία πρέπει να είναι η ίδια ή μετά από την {label}.",beforeDate:"Η ημερομηνία πρέπει να είναι η ίδια ή πριν από την {label}.",startMonth:"Παρακαλώ επιλέξτε ένα μήνα αρχής.",sameMonth:"Αυτές οι δύο ημερομηνίες πρέπει να έχουν τον ίδιο μήνα - θα πρέπει να αλλάξετε ή το ένα ή το άλλο",creditcard:"Ο αριθμός της πιστωτικής κάρτας δεν είναι έγκυρος. Παρακαλούμε ελέγξτε τον αριθμό και δοκιμάστε ξανά. {length} μήκος ψηφίων."});
\ No newline at end of file
diff --git a/trace-viewer/third_party/devscripts/COPYING b/trace-viewer/third_party/devscripts/COPYING
new file mode 100644
index 0000000..c74d291
--- /dev/null
+++ b/trace-viewer/third_party/devscripts/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+       51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/trace-viewer/third_party/devscripts/README.chromium b/trace-viewer/third_party/devscripts/README.chromium
new file mode 100644
index 0000000..1016e4c
--- /dev/null
+++ b/trace-viewer/third_party/devscripts/README.chromium
@@ -0,0 +1,12 @@
+Name: devscripts
+URL: http://anonscm.debian.org/gitweb/?p=devscripts/devscripts.git
+Version: 2.12.4
+Security Critical: no
+License: GPL 2.0
+
+Description:
+This directory contains selected tools from the Debian's devscripts collection.
+
+A .vanilla file is checked in so that our patched version can be easily
+compared with the unpatched script (e.g. when sending the changes upstream).
+Having a .patch file checked in was too inconvenient to keep up to date.
diff --git a/trace-viewer/third_party/devscripts/licensecheck.pl b/trace-viewer/third_party/devscripts/licensecheck.pl
new file mode 100755
index 0000000..a59bbf9
--- /dev/null
+++ b/trace-viewer/third_party/devscripts/licensecheck.pl
@@ -0,0 +1,671 @@
+#!/usr/bin/perl -w
+# This script was originally based on the script of the same name from
+# the KDE SDK (by dfaure@kde.org)
+#
+# This version is
+#   Copyright (C) 2007, 2008 Adam D. Barratt
+#   Copyright (C) 2012 Francesco Poli
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+=head1 NAME
+
+licensecheck - simple license checker for source files
+
+=head1 SYNOPSIS
+
+B<licensecheck> B<--help>|B<--version>
+
+B<licensecheck> [B<--no-conf>] [B<--verbose>] [B<--copyright>]
+[B<-l>|B<--lines=>I<N>] [B<-i>|B<--ignore=>I<regex>] [B<-c>|B<--check=>I<regex>]
+[B<-m>|B<--machine>] [B<-r>|B<--recursive>]
+I<list of files and directories to check>
+
+=head1 DESCRIPTION
+
+B<licensecheck> attempts to determine the license that applies to each file
+passed to it, by searching the start of the file for text belonging to
+various licenses.
+
+If any of the arguments passed are directories, B<licensecheck> will add
+the files contained within to the list of files to process.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--verbose>, B<--no-verbose>
+
+Specify whether to output the text being processed from each file before
+the corresponding license information.
+
+Default is to be quiet.
+
+=item B<-l=>I<N>, B<--lines=>I<N>
+
+Specify the number of lines of each file's header which should be parsed
+for license information. (Default is 60).
+
+=item B<-i=>I<regex>, B<--ignore=>I<regex>
+
+When processing the list of files and directories, the regular
+expression specified by this option will be used to indicate those which
+should not be considered (e.g. backup files, VCS metadata).
+
+=item B<-r>, B<--recursive>
+
+Specify that the contents of directories should be added
+recursively.
+
+=item B<-c=>I<regex>, B<--check=>I<regex>
+
+Specify a pattern against which filenames will be matched in order to
+decide which files to check the license of.
+
+The default includes common source files.
+
+=item B<--copyright>
+
+Also display copyright text found within the file
+
+=item B<-m>, B<--machine>
+
+Display the information in a machine readable way, i.e. in the form
+<file><tab><license>[<tab><copyright>] so that it can be easily sorted
+and/or filtered, e.g. with the B<awk> and B<sort> commands.
+Note that using the B<--verbose> option will kill the readability.
+
+=item B<--no-conf>, B<--noconf>
+
+Do not read any configuration files. This can only be used as the first
+option given on the command-line.
+
+=back
+
+=head1 CONFIGURATION VARIABLES
+
+The two configuration files F</etc/devscripts.conf> and
+F<~/.devscripts> are sourced by a shell in that order to set
+configuration variables.  Command line options can be used to override
+configuration file settings.  Environment variable settings are
+ignored for this purpose.  The currently recognised variables are:
+
+=over 4
+
+=item B<LICENSECHECK_VERBOSE>
+
+If this is set to I<yes>, then it is the same as the B<--verbose> command
+line parameter being used. The default is I<no>.
+
+=item B<LICENSECHECK_PARSELINES>
+
+If this is set to a positive number then the specified number of lines
+at the start of each file will be read whilst attempting to determine
+the license(s) in use.  This is equivalent to the B<--lines> command line
+option.
+
+=back
+
+=head1 LICENSE
+
+This code is copyright by Adam D. Barratt <I<adam@adam-barratt.org.uk>>,
+all rights reserved; based on a script of the same name from the KDE
+SDK, which is copyright by <I<dfaure@kde.org>>.
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the GNU
+General Public License, version 2 or later.
+
+=head1 AUTHOR
+
+Adam D. Barratt <adam@adam-barratt.org.uk>
+
+=cut
+
+use strict;
+use warnings;
+use Getopt::Long qw(:config gnu_getopt);
+use File::Basename;
+use Tie::File;
+use Fcntl 'O_RDONLY';
+
+sub fatal($);
+sub parse_copyright($);
+sub parselicense($);
+sub remove_comments($);
+
+my $progname = basename($0);
+
+# From dpkg-source
+my $default_ignore_regex = '
+# Ignore general backup files
+(?:^|/).*~$|
+# Ignore emacs recovery files
+(?:^|/)\.#.*$|
+# Ignore vi swap files
+(?:^|/)\..*\.swp$|
+# Ignore baz-style junk files or directories
+(?:^|/),,.*(?:$|/.*$)|
+# File-names that should be ignored (never directories)
+(?:^|/)(?:DEADJOE|\.cvsignore|\.arch-inventory|\.bzrignore|\.gitignore)$|
+# File or directory names that should be ignored
+(?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|\.hg|_darcs|\.git|
+\.shelf|_MTN|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
+';
+
+# Take out comments and newlines
+$default_ignore_regex =~ s/^#.*$//mg;
+$default_ignore_regex =~ s/\n//sg;
+
+my $default_check_regex = '\.(c(c|pp|xx)?|h(h|pp|xx)?|f(77|90)?|p(l|m)|xs|sh|php|py(|x)|rb|java|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod|m|tex|mli?)$';
+
+my $modified_conf_msg;
+
+my ($opt_verbose, $opt_lines, $opt_noconf) = ('', '', '');
+my $opt_ignore_regex = $default_ignore_regex;
+my $opt_check_regex = $default_check_regex;
+my $opt_recursive = 0;
+my $opt_copyright = 0;
+my $opt_machine = 0;
+my ($opt_help, $opt_version);
+my $def_lines = 60;
+
+# Read configuration files and then command line
+# This is boilerplate
+
+if (@ARGV and $ARGV[0] =~ /^--no-?conf$/) {
+    $modified_conf_msg = "  (no configuration files read)";
+    shift;
+} else {
+    my @config_files = ('/etc/devscripts.conf', '~/.devscripts');
+    my %config_vars = (
+		       'LICENSECHECK_VERBOSE' => 'no',
+		       'LICENSECHECK_PARSELINES' => $def_lines,
+		      );
+    my %config_default = %config_vars;
+
+    my $shell_cmd;
+    # Set defaults
+    foreach my $var (keys %config_vars) {
+	$shell_cmd .= qq[$var="$config_vars{$var}";\n];
+    }
+    $shell_cmd .= 'for file in ' . join(" ", @config_files) . "; do\n";
+    $shell_cmd .= '[ -f $file ] && . $file; done;' . "\n";
+    # Read back values
+    foreach my $var (keys %config_vars) { $shell_cmd .= "echo \$$var;\n" }
+    my $shell_out = `/bin/bash -c '$shell_cmd'`;
+    @config_vars{keys %config_vars} = split /\n/, $shell_out, -1;
+
+    # Check validity
+    $config_vars{'LICENSECHECK_VERBOSE'} =~ /^(yes|no)$/
+	or $config_vars{'LICENSECHECK_VERBOSE'} = 'no';
+    $config_vars{'LICENSECHECK_PARSELINES'} =~ /^[1-9][0-9]*$/
+	or $config_vars{'LICENSECHECK_PARSELINES'} = $def_lines;
+
+    foreach my $var (sort keys %config_vars) {
+	if ($config_vars{$var} ne $config_default{$var}) {
+	    $modified_conf_msg .= "  $var=$config_vars{$var}\n";
+	}
+    }
+    $modified_conf_msg ||= "  (none)\n";
+    chomp $modified_conf_msg;
+
+    $opt_verbose = $config_vars{'LICENSECHECK_VERBOSE'} eq 'yes' ? 1 : 0;
+    $opt_lines = $config_vars{'LICENSECHECK_PARSELINES'};
+}
+
+GetOptions("help|h" => \$opt_help,
+	   "version|v" => \$opt_version,
+	   "verbose!" => \$opt_verbose,
+	   "lines|l=i" => \$opt_lines,
+	   "ignore|i=s" => \$opt_ignore_regex,
+	   "recursive|r" => \$opt_recursive,
+	   "check|c=s" => \$opt_check_regex,
+	   "copyright" => \$opt_copyright,
+	   "machine|m" => \$opt_machine,
+	   "noconf" => \$opt_noconf,
+	   "no-conf" => \$opt_noconf,
+	   )
+    or die "Usage: $progname [options] filelist\nRun $progname --help for more details\n";
+
+$opt_lines = $def_lines if $opt_lines !~ /^[1-9][0-9]*$/;
+
+if ($opt_noconf) {
+    fatal "--no-conf is only acceptable as the first command-line option!";
+}
+if ($opt_help) { help(); exit 0; }
+if ($opt_version) { version(); exit 0; }
+
+die "Usage: $progname [options] filelist\nRun $progname --help for more details\n" unless @ARGV;
+
+$opt_lines = $def_lines if not defined $opt_lines;
+
+my @files = ();
+my @find_args = ();
+my $files_count = @ARGV;
+
+push @find_args, qw(-not ( -path */LayoutTests/* -prune ) );
+push @find_args, qw(-not ( -path */out/Debug/* -prune ) );
+push @find_args, qw(-not ( -path */out/Release/* -prune ) );
+push @find_args, qw(-not ( -path .git* -prune ) );
+push @find_args, qw(-not ( -path .svn* -prune ) );
+
+push @find_args, qw(-maxdepth 1) unless $opt_recursive;
+push @find_args, qw(-follow -type f -print);
+
+while (@ARGV) {
+    my $file = shift @ARGV;
+
+    if (-d $file) {
+	open FIND, '-|', 'find', $file, @find_args
+	    or die "$progname: couldn't exec find: $!\n";
+
+	while (<FIND>) {
+	    chomp;
+	    next unless m%$opt_check_regex%;
+	    # Skip empty files
+	    next if (-z $_);
+	    push @files, $_ unless m%$opt_ignore_regex%;
+	}
+	close FIND;
+    } else {
+	next unless ($files_count == 1) or $file =~ m%$opt_check_regex%;
+	push @files, $file unless $file =~ m%$opt_ignore_regex%;
+    }
+}
+
+while (@files) {
+    my $file = shift @files;
+    my $header = '';
+    my $copyright_match;
+    my $copyright = '';
+    my $license = '';
+    my %copyrights;
+
+    open (F, "<$file") or die "Unable to access $file\n";
+    while (<F>) {
+        last if ($. > $opt_lines);
+        $header .= $_;
+    }
+    close(F);
+
+    $copyright = join(" / ", values %copyrights);
+
+    print qq(----- $file header -----\n$header----- end header -----\n\n)
+	if $opt_verbose;
+
+    remove_comments($header);
+    $license = parselicense($header);
+
+    # If no license in header, check footer (slow, because read file backwards)
+    # Need for instance for Perl files, which often use the footer
+    if ($license eq "UNKNOWN") {
+        my $footer = '';
+        tie(my @file_lines, "Tie::File", $file, autochomp => 0, mode => O_RDONLY) or die("Unable to access $file\n");
+        # Avoid indexing error if header is entire file
+        if ($#file_lines >= $opt_lines) {
+            foreach (@file_lines[-$opt_lines .. -1]) {
+                $footer .= $_;
+            }
+        }
+        print qq(----- $file footer -----\n$header----- end footer -----\n\n)
+            if $opt_verbose;
+        remove_comments($footer);
+        $license = parselicense($footer);
+    }
+
+    if ($opt_machine) {
+	print "$file\t$license";
+	print "\t" . ($copyright or "*No copyright*") if $opt_copyright;
+	print "\n";
+    } else {
+	print "$file: ";
+	print "*No copyright* " unless $copyright;
+	print $license . "\n";
+	print "  [Copyright: " . $copyright . "]\n"
+	  if $copyright and $opt_copyright;
+	print "\n" if $opt_copyright;
+    }
+}
+
+sub remove_comments($) {
+    $_ = $_[0];
+    # Remove Fortran comments
+    s/^[cC] //gm;
+    # Remove .ASM comments
+    s#^;\*?##gm;
+    # Remove .S comments
+    s#^@ ##gm;
+    # Remove new lines
+    tr/\t\r\n/ /;
+    # Remove C / C++ comments
+    s#(\*/|/[/*])##g;
+    # Remove all characters not matching search
+    tr% A-Za-z.,@;0-9\(\)/-%%cd;
+    # Collapse multiple spaces into single space
+    tr/ //s;
+    $_[0] = $_;
+}
+
+sub parse_copyright($) {
+    my $copyright = '';
+    my $match;
+
+    my $copyright_indicator_regex = '
+	(?:copyright	# The full word
+	|copr\.		# Legally-valid abbreviation
+	|\x{00a9}	# Unicode character COPYRIGHT SIGN
+	|\xc2\xa9	# Unicode copyright sign encoded in iso8859
+	|\(c\)		# Legally-null representation of sign
+	)';
+    my $copyright_disindicator_regex = '
+	\b(?:info(?:rmation)?	# Discussing copyright information
+	|notice			# Discussing the notice
+	|and|or                 # Part of a sentence
+	)\b';
+
+    if (m%$copyright_indicator_regex(?::\s*|\s+)(\S.*)$%ix) {
+	$match = $1;
+
+	# Ignore lines matching "see foo for copyright information" etc.
+	if ($match !~ m%^\s*$copyright_disindicator_regex%ix) {
+	    # De-cruft
+	    $match =~ s/([,.])?\s*$//;
+	    $match =~ s/$copyright_indicator_regex//igx;
+	    $match =~ s/^\s+//;
+	    $match =~ s/\s{2,}/ /g;
+	    $match =~ s/\\@/@/g;
+	    $copyright = $match;
+	}
+    }
+
+    return $copyright;
+}
+
+sub help {
+   print <<"EOF";
+Usage: $progname [options] filename [filename ...]
+Valid options are:
+   --help, -h             Display this message
+   --version, -v          Display version and copyright info
+   --no-conf, --noconf    Don't read devscripts config files; must be
+                          the first option given
+   --verbose              Display the header of each file before its
+                            license information
+   --lines, -l            Specify how many lines of the file header
+                            should be parsed for license information
+                            (Default: $def_lines)
+   --check, -c            Specify a pattern indicating which files should
+                             be checked
+                             (Default: '$default_check_regex')
+   --machine, -m          Display in a machine readable way (good for awk)
+   --recursive, -r        Add the contents of directories recursively
+   --copyright            Also display the file's copyright
+   --ignore, -i           Specify that files / directories matching the
+                            regular expression should be ignored when
+                            checking files
+                            (Default: '$default_ignore_regex')
+
+Default settings modified by devscripts configuration files:
+$modified_conf_msg
+EOF
+}
+
+sub version {
+    print <<"EOF";
+This is $progname, from the Debian devscripts package, version ###VERSION###
+Copyright (C) 2007, 2008 by Adam D. Barratt <adam\@adam-barratt.org.uk>; based
+on a script of the same name from the KDE SDK by <dfaure\@kde.org>.
+
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the
+GNU General Public License, version 2, or (at your option) any
+later version.
+EOF
+}
+
+sub parselicense($) {
+    my ($licensetext) = @_;
+
+    my $gplver = "";
+    my $lgplver = "";
+    my $extrainfo = "";
+    my $license = "";
+
+    if ($licensetext =~ /version ([^, ]+?)[.,]? (?:\(?only\)?.? )?(?:of the GNU (Affero )?General Public License )?(as )?published by the Free Software Foundation/i or
+	$licensetext =~ /GNU (?:Affero )?General Public License (?:as )?published by the Free Software Foundation; version ([^, ]+?)[.,]? /i or
+	$licensetext =~ /GNU (?:Affero )?General Public License,? [Vv]ersion (\d+(?:\.\d+)?)[ \.]/) {
+	$gplver = " (v$1)";
+    } elsif ($licensetext =~ /either version ([^ ]+)(?: of the License)?, or \(at your option\) any later version/) {
+	$gplver = " (v$1 or later)";
+    }
+
+    if ($licensetext =~ /version ([^, ]+?)[.,]? (?:or later|or any later version) (?:of the GNU (?:Lesser |Library )General Public License )(as )?published by the Free Software Foundation/i or
+	$licensetext =~ /(?:GNU (?:Lesser |Library )|(?:Lesser|Library) GNU )General Public License (?:(?:as )?published by the Free Software Foundation;)?,? (?:either )?[Vv]ersion ([^, ]+?)(?: of the license)?[.,]? (?:or later|or (?:\(at your option\) )?any later version)/i or
+	$licensetext =~ /GNU (?:Lesser |Library )General Public License(?: \(LGPL\))?,? [Vv]ersion (\d+(?:\.\d+)?)[ \.]/) {
+	$lgplver = " (v$1 or later)";
+    }
+
+    if ($licensetext =~ /permission (?:is (also granted|given))? to link (the code of )?this program with (any edition of )?(Qt|the Qt library)/i) {
+	$extrainfo = " (with Qt exception)$extrainfo"
+    }
+
+    if ($licensetext =~ /(All changes made in this file will be lost|DO NOT (EDIT|delete this file)|Generated (automatically|by|from)|generated.*file)/i) {
+	$license = "GENERATED FILE";
+    }
+
+    if ($licensetext =~ /is (free software.? you can redistribute it and\/or modify it|licensed) under the terms of (version [^ ]+ of )?the (GNU (Library |Lesser )General Public License|LGPL)/i or
+        $licensetext =~ /(is distributed|may be used|can redistribute).*terms.*(LGPL|(Lesser|Library) GNU General Public License)/) {
+        if ($lgplver) {
+	    $license = "LGPL$lgplver$extrainfo $license";
+        } else {
+	    $license = "LGPL (unversioned/unknown version) $license";
+        }
+    }
+
+    if ($licensetext =~ /is free software.? you (can|may) redistribute it and\/or modify it under the terms of (?:version [^ ]+ (?:\(?only\)? )?of )?the GNU General Public License/i) {
+	$license = "GPL$gplver$extrainfo $license";
+    } elsif ($licensetext =~ /is distributed under the terms of the GNU General Public License,/
+	and $gplver) {
+	$license = "GPL$gplver$extrainfo $license";
+    } elsif ($licensetext =~ /is distributed.*terms.*[^L]GPL/) {
+        if ($gplver) {
+	    $license = "GPL$gplver$extrainfo $license";
+        } else {
+	    $license = "GPL (unversioned/unknown version) $license";
+        }
+    }
+
+    if ($licensetext =~ /This file is part of the .*Qt GUI Toolkit. This file may be distributed under the terms of the Q Public License as defined/) {
+	$license = "QPL (part of Qt) $license";
+    } elsif ($licensetext =~ /may be distributed under the terms of the Q Public License as defined/) {
+	$license = "QPL $license";
+    }
+
+    if ($licensetext =~ /opensource\.org\/licenses\/mit/) {
+	$license = "MIT/X11 (BSD like) $license";
+    } elsif ($licensetext =~ /Permission is hereby granted, free of charge, to any person obtaining a copy of this software and(\/or)? associated documentation files \(the (Software|Materials)\), to deal in the (Software|Materials)/) {
+	$license = "MIT/X11 (BSD like) $license";
+    } elsif ($licensetext =~ /Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose/) {
+	$license = "MIT/X11 (BSD like) $license";
+    } elsif ($licensetext =~ /Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee/) {
+	$license = "MIT/X11 (BSD like) $license";
+    } elsif ($licensetext  =~ /MIT .* License/) {
+	$license = "MIT/X11 (BSD like) $license";
+    }
+
+    if ($licensetext  =~ /This file is part of the Independent JPEG Group(')?s software.*For conditions of distribution and use, see the accompanying README file/i) {
+	$license = "Independent JPEG Group License $license";
+    }
+
+    if ($licensetext  =~ /the University of Illinois Open Source License/){
+	$license = "University of Illinois/NCSA Open Source License (BSD like) $license";
+    }
+
+    if ($licensetext  =~ /Permission to use, copy, modify, and(\/or)? distribute this software (and its documentation )?for any purpose (with or )?without fee is hereby granted, provided.*(copyright|entire) notice.*all copies/i) {
+	$license = "ISC $license";
+    }
+
+    if ($licensetext =~ /THIS SOFTWARE IS PROVIDED .*AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY/ ||
+        $licensetext =~ /THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- ITY/) {
+	if ($licensetext =~ /All advertising materials mentioning features or use of this software must display the following/) {
+	    $license = "BSD (4 clause) $license";
+	} elsif ($licensetext =~ /be used to endorse or promote products derived from this software/) {
+	    $license = "BSD (3 clause) $license";
+	} elsif ($licensetext =~ /Redistributions of source code must retain the above copyright notice/) {
+	    $license = "BSD (2 clause) $license";
+	} else {
+	    $license = "BSD $license";
+	}
+    } elsif ($licensetext =~ /Use of this source code is governed by a BSD-style license/) {
+        $license = "BSD-like $license";
+    } elsif ($licensetext =~ /BSD terms apply/) {
+        $license = "BSD-like $license";
+    } elsif ($licensetext =~ /subject to the BSD License/) {
+        # TODO(sbc): remove this case once we fix: http://crbug.com/177268
+        $license = "BSD-like $license";
+    } elsif ($licensetext =~ /license BSD/) {
+        $license = "BSD-like $license";
+    } elsif ($licensetext =~ /GOVERNED BY A BSD-STYLE SOURCE LICENSE/) {
+        $license = "BSD-like $license";
+    } elsif ($licensetext =~ /BSD 3-Clause license/) {
+        $license = "BSD (3 clause) $license";
+    }
+
+    if ($licensetext =~ /Mozilla Public License( Version|, v.) ([^ ]+[^., ]),?/) {
+	$license = "MPL (v$2) $license";
+    }
+
+    if ($licensetext =~ /Released under the terms of the Artistic License ([^ ]+)/) {
+	$license = "Artistic (v$1) $license";
+    }
+
+    if ($licensetext =~ /is free software under the Artistic [Ll]icense/) {
+	$license = "Artistic $license";
+    }
+
+    if ($licensetext =~ /This (program|library) is free software; you can redistribute it and\/or modify it under the same terms as Perl itself/) {
+	$license = "Perl $license";
+    }
+
+    if ($licensetext =~ /under the terms of the Apache ([^ ]+) License OR version 2 of the GNU/) {
+	$license = "Apache (v$1) GPL (v2) $license";
+    } elsif ($licensetext =~ /under the Apache License, Version ([^ ]+)/) {
+	$license = "Apache (v$1) $license";
+    }
+
+    if ($licensetext =~ /(THE BEER-WARE LICENSE)/i) {
+	$license = "Beerware $license";
+    }
+
+    if ($licensetext =~ /This source file is subject to version ([^ ]+) of the PHP license/) {
+	$license = "PHP (v$1) $license";
+    }
+
+    if ($licensetext =~ /under the terms of the CeCILL /) {
+	$license = "CeCILL $license";
+    }
+
+    if ($licensetext =~ /under the terms of the CeCILL-([^ ]+) /) {
+	$license = "CeCILL-$1 $license";
+    }
+
+    if ($licensetext =~ /under the SGI Free Software (B License|License B)/) {
+	$license = "SGI Free Software License B $license";
+    }
+
+    if ($licensetext =~ /(in|into) the public domain/i) {
+	$license = "Public domain $license";
+    }
+
+    if ($licensetext =~ /terms of the Common Development and Distribution License(, Version ([^(]+))? \(the License\)/) {
+	$license = "CDDL " . ($1 ? "(v$2) " : '') . $license;
+    }
+
+    if ($licensetext =~ /Microsoft Permissive License \(Ms-PL\)/) {
+        $license = "Ms-PL $license";
+    }
+
+    if ($licensetext =~ /as defined in and that are subject to the Apple Public Source License([ ,-]+Version ([^ ]+)?(\.))/) {
+	$license = "APSL " . ($1 ? "(v$2) " : '') . $license;
+    } elsif ($licensetext =~ /provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software/) {
+	# https://fedoraproject.org/wiki/Licensing/Apple_MIT_License
+	$license = "Apple MIT $license";
+    }
+
+    if ($licensetext =~ /Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license \([\"]?the Software[\"]?\)/ or
+	$licensetext =~ /Boost Software License([ ,-]+Version ([^ ]+)?(\.))/i) {
+	$license = "BSL " . ($1 ? "(v$2) " : '') . $license;
+    }
+
+    if ($licensetext =~ /PYTHON SOFTWARE FOUNDATION LICENSE (VERSION ([^ ]+))/i) {
+	$license = "PSF " . ($1 ? "(v$2) " : '') . $license;
+    }
+
+    if ($licensetext =~ /The origin of this software must not be misrepresented.*Altered source versions must be plainly marked as such.*This notice may not be removed or altered from any source distribution/ or
+        $licensetext =~ /see copyright notice in zlib\.h/) {
+	$license = "zlib/libpng $license";
+    } elsif ($licensetext =~ /This code is released under the libpng license/) {
+        $license = "libpng $license";
+    }
+
+    if ($licensetext =~ /under MIT license/) {
+        $license = "MIT/X11 (BSD like) $license";
+    }
+
+    if ($licensetext =~ /License MIT(-| )License/) {
+        $license = "MIT/X11 (BSD like) $license";
+    }
+
+    if ($licensetext =~ /As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice/) {
+        $license = $license . "with Bison parser exception";
+    }
+
+    if ($licensetext =~ /As a special exception to the GNU General Public License, if you distribute this file as part of a program or library that is built using GNU Libtool, you may include this file under the same distribution terms that you use for the rest of that program/) {
+        $license = $license . "with libtool exception";
+    }
+
+    if ($licensetext =~ /These materials are protected by copyright laws and contain material proprietary to the Khronos Group, Inc\. You may use these materials for implementing Khronos specifications, without altering or removing any trademark, copyright or other notice from the specification/) {
+        $license = $license . "Khronos Group";
+    }
+
+    if ($licensetext =~ /This file is part of the FreeType project, and may only be used(,)? modified(,)? and distributed under the terms of the FreeType project license, LICENSE\.TXT\. By continuing to use, modify, or distribute this file you indicate that you have read the license and understand and accept it fully/) {
+        $license = "FreeType (BSD like) $license";
+    }
+    if ($licensetext =~ /This software, and all works of authorship, whether in source or object code form as indicated by the copyright notice.*is made available, and may only be used, modified, and distributed under the FreeType Project License, LICENSE\.TXT\. Additionally, subject to the terms and conditions of the FreeType Project License, each contributor to the Work hereby grants to any individual or legal entity exercising permissions granted by the FreeType Project License and this section.*a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable.*patent license to make/) {
+        $license = "FreeType (BSD like) with patent clause $license";
+    }
+
+    if ($licensetext =~ /Anti-Grain Geometry.*Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided as is without express or impl/) {
+        $license = "Anti-Grain Geometry $license";
+    }
+
+    if ($licensetext =~ /Developed at SunSoft, a Sun Microsystems, Inc\. business\. Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved\./) {
+        $license = "SunSoft (BSD like) $license";
+    }
+
+    $license = "UNKNOWN" unless $license;
+
+    # Remove trailing spaces.
+    $license =~ s/\s+$//;
+
+    return $license;
+}
+
+sub fatal($) {
+    my ($pack,$file,$line);
+    ($pack,$file,$line) = caller();
+    (my $msg = "$progname: fatal error at line $line:\n@_\n") =~ tr/\0//d;
+    $msg =~ s/\n\n$/\n/;
+    die $msg;
+}
diff --git a/trace-viewer/third_party/devscripts/licensecheck.pl.vanilla b/trace-viewer/third_party/devscripts/licensecheck.pl.vanilla
new file mode 100644
index 0000000..d98b974
--- /dev/null
+++ b/trace-viewer/third_party/devscripts/licensecheck.pl.vanilla
@@ -0,0 +1,577 @@
+#!/usr/bin/perl -w
+# This script was originally based on the script of the same name from
+# the KDE SDK (by dfaure@kde.org)
+#
+# This version is
+#   Copyright (C) 2007, 2008 Adam D. Barratt
+#   Copyright (C) 2012 Francesco Poli
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+=head1 NAME
+
+licensecheck - simple license checker for source files
+
+=head1 SYNOPSIS
+
+B<licensecheck> B<--help>|B<--version>
+
+B<licensecheck> [B<--no-conf>] [B<--verbose>] [B<--copyright>]
+[B<-l>|B<--lines=>I<N>] [B<-i>|B<--ignore=>I<regex>] [B<-c>|B<--check=>I<regex>]
+[B<-m>|B<--machine>] [B<-r>|B<--recursive>]
+I<list of files and directories to check>
+
+=head1 DESCRIPTION
+
+B<licensecheck> attempts to determine the license that applies to each file
+passed to it, by searching the start of the file for text belonging to
+various licenses.
+
+If any of the arguments passed are directories, B<licensecheck> will add
+the files contained within to the list of files to process.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--verbose>, B<--no-verbose>
+
+Specify whether to output the text being processed from each file before
+the corresponding license information.
+
+Default is to be quiet.
+
+=item B<-l=>I<N>, B<--lines=>I<N>
+
+Specify the number of lines of each file's header which should be parsed
+for license information. (Default is 60).
+
+=item B<-i=>I<regex>, B<--ignore=>I<regex>
+
+When processing the list of files and directories, the regular
+expression specified by this option will be used to indicate those which
+should not be considered (e.g. backup files, VCS metadata).
+
+=item B<-r>, B<--recursive>
+
+Specify that the contents of directories should be added
+recursively.
+
+=item B<-c=>I<regex>, B<--check=>I<regex>
+
+Specify a pattern against which filenames will be matched in order to
+decide which files to check the license of.
+
+The default includes common source files.
+
+=item B<--copyright>
+
+Also display copyright text found within the file
+
+=item B<-m>, B<--machine>
+
+Display the information in a machine readable way, i.e. in the form
+<file><tab><license>[<tab><copyright>] so that it can be easily sorted
+and/or filtered, e.g. with the B<awk> and B<sort> commands.
+Note that using the B<--verbose> option will kill the readability.
+
+=item B<--no-conf>, B<--noconf>
+
+Do not read any configuration files. This can only be used as the first
+option given on the command-line.
+
+=back
+
+=head1 CONFIGURATION VARIABLES
+
+The two configuration files F</etc/devscripts.conf> and
+F<~/.devscripts> are sourced by a shell in that order to set
+configuration variables.  Command line options can be used to override
+configuration file settings.  Environment variable settings are
+ignored for this purpose.  The currently recognised variables are:
+
+=over 4
+
+=item B<LICENSECHECK_VERBOSE>
+
+If this is set to I<yes>, then it is the same as the B<--verbose> command
+line parameter being used. The default is I<no>.
+
+=item B<LICENSECHECK_PARSELINES>
+
+If this is set to a positive number then the specified number of lines
+at the start of each file will be read whilst attempting to determine
+the license(s) in use.  This is equivalent to the B<--lines> command line
+option.
+
+=back
+
+=head1 LICENSE
+
+This code is copyright by Adam D. Barratt <I<adam@adam-barratt.org.uk>>,
+all rights reserved; based on a script of the same name from the KDE
+SDK, which is copyright by <I<dfaure@kde.org>>.
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the GNU
+General Public License, version 2 or later.
+
+=head1 AUTHOR
+
+Adam D. Barratt <adam@adam-barratt.org.uk>
+
+=cut
+
+use strict;
+use warnings;
+use Getopt::Long qw(:config gnu_getopt);
+use File::Basename;
+
+sub fatal($);
+sub parse_copyright($);
+sub parselicense($);
+
+my $progname = basename($0);
+
+# From dpkg-source
+my $default_ignore_regex = '
+# Ignore general backup files
+(?:^|/).*~$|
+# Ignore emacs recovery files
+(?:^|/)\.#.*$|
+# Ignore vi swap files
+(?:^|/)\..*\.swp$|
+# Ignore baz-style junk files or directories
+(?:^|/),,.*(?:$|/.*$)|
+# File-names that should be ignored (never directories)
+(?:^|/)(?:DEADJOE|\.cvsignore|\.arch-inventory|\.bzrignore|\.gitignore)$|
+# File or directory names that should be ignored
+(?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|\.hg|_darcs|\.git|
+\.shelf|_MTN|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
+';
+
+# Take out comments and newlines
+$default_ignore_regex =~ s/^#.*$//mg;
+$default_ignore_regex =~ s/\n//sg;
+
+my $default_check_regex = '\.(c(c|pp|xx)?|h(h|pp|xx)?|f(77|90)?|p(l|m)|xs|sh|php|py(|x)|rb|java|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod|m|tex|mli?)$';
+
+my $modified_conf_msg;
+
+my ($opt_verbose, $opt_lines, $opt_noconf, $opt_ignore_regex, $opt_check_regex)
+  = ('', '', '', '', '');
+my $opt_recursive = 0;
+my $opt_copyright = 0;
+my $opt_machine = 0;
+my ($opt_help, $opt_version);
+my $def_lines = 60;
+
+# Read configuration files and then command line
+# This is boilerplate
+
+if (@ARGV and $ARGV[0] =~ /^--no-?conf$/) {
+    $modified_conf_msg = "  (no configuration files read)";
+    shift;
+} else {
+    my @config_files = ('/etc/devscripts.conf', '~/.devscripts');
+    my %config_vars = (
+		       'LICENSECHECK_VERBOSE' => 'no',
+		       'LICENSECHECK_PARSELINES' => $def_lines,
+		      );
+    my %config_default = %config_vars;
+
+    my $shell_cmd;
+    # Set defaults
+    foreach my $var (keys %config_vars) {
+	$shell_cmd .= qq[$var="$config_vars{$var}";\n];
+    }
+    $shell_cmd .= 'for file in ' . join(" ", @config_files) . "; do\n";
+    $shell_cmd .= '[ -f $file ] && . $file; done;' . "\n";
+    # Read back values
+    foreach my $var (keys %config_vars) { $shell_cmd .= "echo \$$var;\n" }
+    my $shell_out = `/bin/bash -c '$shell_cmd'`;
+    @config_vars{keys %config_vars} = split /\n/, $shell_out, -1;
+
+    # Check validity
+    $config_vars{'LICENSECHECK_VERBOSE'} =~ /^(yes|no)$/
+	or $config_vars{'LICENSECHECK_VERBOSE'} = 'no';
+    $config_vars{'LICENSECHECK_PARSELINES'} =~ /^[1-9][0-9]*$/
+	or $config_vars{'LICENSECHECK_PARSELINES'} = $def_lines;
+
+    foreach my $var (sort keys %config_vars) {
+	if ($config_vars{$var} ne $config_default{$var}) {
+	    $modified_conf_msg .= "  $var=$config_vars{$var}\n";
+	}
+    }
+    $modified_conf_msg ||= "  (none)\n";
+    chomp $modified_conf_msg;
+
+    $opt_verbose = $config_vars{'LICENSECHECK_VERBOSE'} eq 'yes' ? 1 : 0;
+    $opt_lines = $config_vars{'LICENSECHECK_PARSELINES'};
+}
+
+GetOptions("help|h" => \$opt_help,
+	   "version|v" => \$opt_version,
+	   "verbose!" => \$opt_verbose,
+	   "lines|l=i" => \$opt_lines,
+	   "ignore|i=s" => \$opt_ignore_regex,
+	   "recursive|r" => \$opt_recursive,
+	   "check|c=s" => \$opt_check_regex,
+	   "copyright" => \$opt_copyright,
+	   "machine|m" => \$opt_machine,
+	   "noconf" => \$opt_noconf,
+	   "no-conf" => \$opt_noconf,
+	   )
+    or die "Usage: $progname [options] filelist\nRun $progname --help for more details\n";
+
+$opt_lines = $def_lines if $opt_lines !~ /^[1-9][0-9]*$/;
+$opt_ignore_regex = $default_ignore_regex if ! length $opt_ignore_regex;
+$opt_check_regex = $default_check_regex if ! length $opt_check_regex;
+
+if ($opt_noconf) {
+    fatal "--no-conf is only acceptable as the first command-line option!";
+}
+if ($opt_help) { help(); exit 0; }
+if ($opt_version) { version(); exit 0; }
+
+die "Usage: $progname [options] filelist\nRun $progname --help for more details\n" unless @ARGV;
+
+$opt_lines = $def_lines if not defined $opt_lines;
+
+my @files = ();
+my @find_args = ();
+my $files_count = @ARGV;
+
+push @find_args, qw(-maxdepth 1) unless $opt_recursive;
+push @find_args, qw(-follow -type f -print);
+
+while (@ARGV) {
+    my $file = shift @ARGV;
+
+    if (-d $file) {
+	open FIND, '-|', 'find', $file, @find_args
+	    or die "$progname: couldn't exec find: $!\n";
+
+	while (<FIND>) {
+	    chomp;
+	    next unless m%$opt_check_regex%;
+	    # Skip empty files
+	    next if (-z $_);
+	    push @files, $_ unless m%$opt_ignore_regex%;
+	}
+	close FIND;
+    } else {
+	next unless ($files_count == 1) or $file =~ m%$opt_check_regex%;
+	push @files, $file unless $file =~ m%$opt_ignore_regex%;
+    }
+}
+
+while (@files) {
+    my $file = shift @files;
+    my $content = '';
+    my $copyright_match;
+    my $copyright = '';
+    my $license = '';
+    my %copyrights;
+
+    open (F, "<$file") or die "Unable to access $file\n";
+    while (<F>) {
+        last if ($. > $opt_lines);
+        $content .= $_;
+	$copyright_match = parse_copyright($_);
+	if ($copyright_match) {
+	    $copyrights{lc("$copyright_match")} = "$copyright_match";
+	}
+    }
+    close(F);
+
+    $copyright = join(" / ", values %copyrights);
+
+    print qq(----- $file header -----\n$content----- end header -----\n\n)
+	if $opt_verbose;
+
+    # Remove Fortran comments
+    $content =~ s/^[cC] //gm;
+    $content =~ tr/\t\r\n/ /;
+    # Remove C / C++ comments
+    $content =~ s#(\*/|/[/*])##g;
+    $content =~ tr% A-Za-z.,@;0-9\(\)/-%%cd;
+    $content =~ tr/ //s;
+
+    $license = parselicense($content);
+    if ($opt_machine) {
+	print "$file\t$license";
+	print "\t" . ($copyright or "*No copyright*") if $opt_copyright;
+	print "\n";
+    } else {
+	print "$file: ";
+	print "*No copyright* " unless $copyright;
+	print $license . "\n";
+	print "  [Copyright: " . $copyright . "]\n"
+	  if $copyright and $opt_copyright;
+	print "\n" if $opt_copyright;
+    }
+}
+
+sub parse_copyright($) {
+    my $copyright = '';
+    my $match;
+
+    my $copyright_indicator_regex = '
+	(?:copyright	# The full word
+	|copr\.		# Legally-valid abbreviation
+	|\x{00a9}	# Unicode character COPYRIGHT SIGN
+	|\xc2\xa9	# Unicode copyright sign encoded in iso8859
+	|\(c\)		# Legally-null representation of sign
+	)';
+    my $copyright_disindicator_regex = '
+	\b(?:info(?:rmation)?	# Discussing copyright information
+	|notice			# Discussing the notice
+	|and|or                 # Part of a sentence
+	)\b';
+
+    if (m%$copyright_indicator_regex(?::\s*|\s+)(\S.*)$%ix) {
+	$match = $1;
+
+	# Ignore lines matching "see foo for copyright information" etc.
+	if ($match !~ m%^\s*$copyright_disindicator_regex%ix) {
+	    # De-cruft
+	    $match =~ s/([,.])?\s*$//;
+	    $match =~ s/$copyright_indicator_regex//igx;
+	    $match =~ s/^\s+//;
+	    $match =~ s/\s{2,}/ /g;
+	    $match =~ s/\\@/@/g;
+	    $copyright = $match;
+	}
+    }
+
+    return $copyright;
+}
+
+sub help {
+   print <<"EOF";
+Usage: $progname [options] filename [filename ...]
+Valid options are:
+   --help, -h             Display this message
+   --version, -v          Display version and copyright info
+   --no-conf, --noconf    Don't read devscripts config files; must be
+                          the first option given
+   --verbose              Display the header of each file before its
+                            license information
+   --lines, -l            Specify how many lines of the file header
+                            should be parsed for license information
+                            (Default: $def_lines)
+   --check, -c            Specify a pattern indicating which files should
+                             be checked
+                             (Default: '$default_check_regex')
+   --machine, -m          Display in a machine readable way (good for awk)
+   --recursive, -r        Add the contents of directories recursively
+   --copyright            Also display the file's copyright
+   --ignore, -i           Specify that files / directories matching the
+                            regular expression should be ignored when
+                            checking files
+                            (Default: '$default_ignore_regex')
+
+Default settings modified by devscripts configuration files:
+$modified_conf_msg
+EOF
+}
+
+sub version {
+    print <<"EOF";
+This is $progname, from the Debian devscripts package, version ###VERSION###
+Copyright (C) 2007, 2008 by Adam D. Barratt <adam\@adam-barratt.org.uk>; based
+on a script of the same name from the KDE SDK by <dfaure\@kde.org>.
+
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the
+GNU General Public License, version 2, or (at your option) any
+later version.
+EOF
+}
+
+sub parselicense($) {
+    my ($licensetext) = @_;
+
+    my $gplver = "";
+    my $extrainfo = "";
+    my $license = "";
+
+    if ($licensetext =~ /version ([^, ]+?)[.,]? (?:\(?only\)?.? )?(?:of the GNU (Affero )?(Lesser |Library )?General Public License )?(as )?published by the Free Software Foundation/i or
+	$licensetext =~ /GNU (?:Affero )?(?:Lesser |Library )?General Public License (?:as )?published by the Free Software Foundation; version ([^, ]+?)[.,]? /i) {
+
+	$gplver = " (v$1)";
+    } elsif ($licensetext =~ /GNU (?:Affero )?(?:Lesser |Library )?General Public License, version (\d+(?:\.\d+)?)[ \.]/) {
+	$gplver = " (v$1)";
+    } elsif ($licensetext =~ /either version ([^ ]+)(?: of the License)?, or \(at your option\) any later version/) {
+	$gplver = " (v$1 or later)";
+    }
+
+    if ($licensetext =~ /(?:675 Mass Ave|59 Temple Place|51 Franklin Steet|02139|02111-1307)/i) {
+	$extrainfo = " (with incorrect FSF address)$extrainfo";
+    }
+
+    if ($licensetext =~ /permission (?:is (also granted|given))? to link (the code of )?this program with (any edition of )?(Qt|the Qt library)/i) {
+	$extrainfo = " (with Qt exception)$extrainfo"
+    }
+
+    if ($licensetext =~ /(All changes made in this file will be lost|DO NOT (EDIT|delete this file)|Generated (automatically|by|from)|generated.*file)/i) {
+	$license = "GENERATED FILE";
+    }
+
+    if ($licensetext =~ /is (free software.? you can redistribute it and\/or modify it|licensed) under the terms of (version [^ ]+ of )?the (GNU (Library |Lesser )General Public License|LGPL)/i) {
+	$license = "LGPL$gplver$extrainfo $license";
+    }
+
+    if ($licensetext =~ /is free software.? you can redistribute it and\/or modify it under the terms of the (GNU Affero General Public License|AGPL)/i) {
+	$license = "AGPL$gplver$extrainfo $license";
+    }
+
+    if ($licensetext =~ /is free software.? you (can|may) redistribute it and\/or modify it under the terms of (?:version [^ ]+ (?:\(?only\)? )?of )?the GNU General Public License/i) {
+	$license = "GPL$gplver$extrainfo $license";
+    }
+
+    if ($licensetext =~ /is distributed under the terms of the GNU General Public License,/
+	and length $gplver) {
+	$license = "GPL$gplver$extrainfo $license";
+    }
+
+    if ($licensetext =~ /is distributed.*terms.*GPL/) {
+	$license = "GPL (unversioned/unknown version) $license";
+    }
+
+    if ($licensetext =~ /This file is part of the .*Qt GUI Toolkit. This file may be distributed under the terms of the Q Public License as defined/) {
+	$license = "QPL (part of Qt) $license";
+    } elsif ($licensetext =~ /may be distributed under the terms of the Q Public License as defined/) {
+	$license = "QPL $license";
+    }
+
+    if ($licensetext =~ /opensource\.org\/licenses\/mit-license\.php/) {
+	$license = "MIT/X11 (BSD like) $license";
+    } elsif ($licensetext =~ /Permission is hereby granted, free of charge, to any person obtaining a copy of this software and(\/or)? associated documentation files \(the (Software|Materials)\), to deal in the (Software|Materials)/) {
+	$license = "MIT/X11 (BSD like) $license";
+    } elsif ($licensetext =~ /Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose/) {
+	$license = "MIT/X11 (BSD like) $license";
+    }
+
+    if ($licensetext  =~ /Permission to use, copy, modify, and(\/or)? distribute this software for any purpose with or without fee is hereby granted, provided.*copyright notice.*permission notice.*all copies/) {
+	$license = "ISC $license";
+    }
+
+    if ($licensetext =~ /THIS SOFTWARE IS PROVIDED .*AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY/) {
+	if ($licensetext =~ /All advertising materials mentioning features or use of this software must display the following acknowledge?ment.*This product includes software developed by/i) {
+	    $license = "BSD (4 clause) $license";
+	} elsif ($licensetext =~ /(The name .*? may not|Neither the names? .*? nor the names of (its|their) contributors may) be used to endorse or promote products derived from this software/i) {
+	    $license = "BSD (3 clause) $license";
+	} elsif ($licensetext =~ /Redistributions of source code must retain the above copyright notice/i) {
+	    $license = "BSD (2 clause) $license";
+	} else {
+	    $license = "BSD $license";
+	}
+    }
+
+    if ($licensetext =~ /Mozilla Public License Version ([^ ]+)/) {
+	$license = "MPL (v$1) $license";
+    }
+
+    if ($licensetext =~ /Released under the terms of the Artistic License ([^ ]+)/) {
+	$license = "Artistic (v$1) $license";
+    }
+
+    if ($licensetext =~ /is free software under the Artistic [Ll]icense/) {
+	$license = "Artistic $license";
+    }
+
+    if ($licensetext =~ /This program is free software; you can redistribute it and\/or modify it under the same terms as Perl itself/) {
+	$license = "Perl $license";
+    }
+
+    if ($licensetext =~ /under the Apache License, Version ([^ ]+)/) {
+	$license = "Apache (v$1) $license";
+    }
+
+    if ($licensetext =~ /(THE BEER-WARE LICENSE)/i) {
+	$license = "Beerware $license";
+    }
+
+    if ($licensetext =~ /This source file is subject to version ([^ ]+) of the PHP license/) {
+	$license = "PHP (v$1) $license";
+    }
+
+    if ($licensetext =~ /under the terms of the CeCILL /) {
+	$license = "CeCILL $license";
+    }
+
+    if ($licensetext =~ /under the terms of the CeCILL-([^ ]+) /) {
+	$license = "CeCILL-$1 $license";
+    }
+
+    if ($licensetext =~ /under the SGI Free Software License B/) {
+	$license = "SGI Free Software License B $license";
+    }
+
+    if ($licensetext =~ /is in the public domain/i) {
+	$license = "Public domain $license";
+    }
+
+    if ($licensetext =~ /terms of the Common Development and Distribution License(, Version ([^(]+))? \(the License\)/) {
+	$license = "CDDL " . ($1 ? "(v$2) " : '') . $license;
+    }
+
+    if ($licensetext =~ /Microsoft Permissive License \(Ms-PL\)/) {
+        $license = "Ms-PL $license";
+    }
+
+    if ($licensetext =~ /Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license \(the \"Software\"\)/ or
+	$licensetext =~ /Boost Software License([ ,-]+Version ([^ ]+)?(\.))/i) {
+	$license = "BSL " . ($1 ? "(v$2) " : '') . $license;
+    }
+
+    if ($licensetext =~ /PYTHON SOFTWARE FOUNDATION LICENSE (VERSION ([^ ]+))/i) {
+	$license = "PSF " . ($1 ? "(v$2) " : '') . $license;
+    }
+
+    if ($licensetext =~ /The origin of this software must not be misrepresented.*Altered source versions must be plainly marked as such.*This notice may not be removed or altered from any source distribution/ or
+        $licensetext =~ /see copyright notice in zlib\.h/) {
+	$license = "zlib/libpng $license";
+    } elsif ($licensetext =~ /This code is released under the libpng license/) {
+        $license = "libpng $license";
+    }
+
+    if ($licensetext =~ /Do What The Fuck You Want To Public License, Version ([^, ]+)/i) {
+        $license = "WTFPL (v$1) $license";
+    }
+
+    if ($licensetext =~ /Do what The Fuck You Want To Public License/i) {
+        $license = "WTFPL $license";
+    }
+
+    if ($licensetext =~ /(License WTFPL|Under (the|a) WTFPL)/i) {
+        $license = "WTFPL $license";
+    }
+
+    $license = "UNKNOWN" if (!length($license));
+
+    # Remove trailing spaces.
+    $license =~ s/\s+$//;
+
+    return $license;
+}
+
+sub fatal($) {
+    my ($pack,$file,$line);
+    ($pack,$file,$line) = caller();
+    (my $msg = "$progname: fatal error at line $line:\n@_\n") =~ tr/\0//d;
+    $msg =~ s/\n\n$/\n/;
+    die $msg;
+}
diff --git a/trace-viewer/third_party/gl-matrix/jsdoc-template/static/header.html b/trace-viewer/third_party/gl-matrix/jsdoc-template/static/header.html
index 353b735..7b81904 100644
--- a/trace-viewer/third_party/gl-matrix/jsdoc-template/static/header.html
+++ b/trace-viewer/third_party/gl-matrix/jsdoc-template/static/header.html
@@ -1,2 +1,2 @@
 <div id="header">
-</div>
\ No newline at end of file
+</div>
diff --git a/trace-viewer/third_party/gl-matrix/jsdoc-template/static/index.html b/trace-viewer/third_party/gl-matrix/jsdoc-template/static/index.html
index d51d4ef..adaa3b5 100644
--- a/trace-viewer/third_party/gl-matrix/jsdoc-template/static/index.html
+++ b/trace-viewer/third_party/gl-matrix/jsdoc-template/static/index.html
@@ -16,4 +16,4 @@
 		</body>
 	</noframes>
 </frameset>
-</html>
\ No newline at end of file
+</html>
diff --git a/trace-viewer/third_party/tvcm/tvcm/dev_server.py b/trace-viewer/third_party/tvcm/tvcm/dev_server.py
index 855418e..4d0b54d 100644
--- a/trace-viewer/third_party/tvcm/tvcm/dev_server.py
+++ b/trace-viewer/third_party/tvcm/tvcm/dev_server.py
@@ -20,6 +20,7 @@
 import StringIO
 import BaseHTTPServer
 
+TEST_DATA_PREFIX = '/test_data'
 
 class DevServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
   def __init__(self, *args, **kwargs):
@@ -58,6 +59,10 @@
   def translate_path(self, path):
     path = path.split('?',1)[0]
     path = path.split('#',1)[0]
+
+    if path.startswith(TEST_DATA_PREFIX):
+      path = path[len(TEST_DATA_PREFIX):]
+
     for mapped_path in self.server.project.source_paths:
       rel = os.path.relpath(path, '/')
       candidate = os.path.join(mapped_path, rel)
@@ -207,6 +212,10 @@
   def port(self):
     return self._port
 
+  @property
+  def data_dir(self):
+    return self._data_dir
+
   def serve_forever(self):
     if not self._quiet:
       sys.stderr.write("Now running on http://localhost:%i\n" % self._port)
diff --git a/trace-viewer/third_party/tvcm/tvcm/html_module.py b/trace-viewer/third_party/tvcm/tvcm/html_module.py
index 4b4cc5f..b90db21 100644
--- a/trace-viewer/third_party/tvcm/tvcm/html_module.py
+++ b/trace-viewer/third_party/tvcm/tvcm/html_module.py
@@ -36,14 +36,14 @@
 
     reachable_names = set([m.name
                            for m in self.all_dependent_modules_recursive])
-    if 'tv.exportTo' in self.contents:
+    if 'tr.exportTo' in self.contents:
       if 'base.base' not in reachable_names:
         raise Exception('%s: Does not have a dependency on base' % os.path.relpath(self.resource.absolute_path))
 
     """
-    if 'tv.unittest.testSuite' in self.contents:
-      if 'tv.unittest' not in reachable_names:
-        raise Exception('%s: Does not have a dependency on tv.unittest' % os.path.relpath(self.resource.absolute_path))
+    if 'tr.unittest.testSuite' in self.contents:
+      if 'tr.unittest' not in reachable_names:
+        raise Exception('%s: Does not have a dependency on tr.unittest' % os.path.relpath(self.resource.absolute_path))
     """
 
   def GetTVCMDepsModuleType(self):
diff --git a/trace-viewer/third_party/v8/LICENSE b/trace-viewer/third_party/v8/LICENSE
new file mode 100644
index 0000000..2f5bce8
--- /dev/null
+++ b/trace-viewer/third_party/v8/LICENSE
@@ -0,0 +1,54 @@
+This license applies to all parts of V8 that are not externally
+maintained libraries.  The externally maintained libraries used by V8
+are:
+
+  - PCRE test suite, located in
+    test/mjsunit/third_party/regexp-pcre.js.  This is based on the
+    test suite from PCRE-7.3, which is copyrighted by the University
+    of Cambridge and Google, Inc.  The copyright notice and license
+    are embedded in regexp-pcre.js.
+
+  - Layout tests, located in test/mjsunit/third_party.  These are
+    based on layout tests from webkit.org which are copyrighted by
+    Apple Computer, Inc. and released under a 3-clause BSD license.
+
+  - Strongtalk assembler, the basis of the files assembler-arm-inl.h,
+    assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,
+    assembler-ia32.cc, assembler-ia32.h, assembler-x64-inl.h,
+    assembler-x64.cc, assembler-x64.h, assembler-mips-inl.h,
+    assembler-mips.cc, assembler-mips.h, assembler.cc and assembler.h.
+    This code is copyrighted by Sun Microsystems Inc. and released
+    under a 3-clause BSD license.
+
+  - Valgrind client API header, located at third_party/valgrind/valgrind.h
+    This is release under the BSD license.
+
+These libraries have their own licenses; we recommend you read them,
+as their terms may differ from the terms below.
+
+Copyright 2014, the V8 project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/trace-viewer/third_party/v8/LICENSE.strongtalk b/trace-viewer/third_party/v8/LICENSE.strongtalk
new file mode 100644
index 0000000..9bd62e4
--- /dev/null
+++ b/trace-viewer/third_party/v8/LICENSE.strongtalk
@@ -0,0 +1,29 @@
+Copyright (c) 1994-2006 Sun Microsystems Inc.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+- Redistribution in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of Sun Microsystems or the names of contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/trace-viewer/third_party/v8/LICENSE.v8 b/trace-viewer/third_party/v8/LICENSE.v8
new file mode 100644
index 0000000..933718a
--- /dev/null
+++ b/trace-viewer/third_party/v8/LICENSE.v8
@@ -0,0 +1,26 @@
+Copyright 2006-2011, the V8 project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/trace-viewer/third_party/v8/LICENSE.valgrind b/trace-viewer/third_party/v8/LICENSE.valgrind
new file mode 100644
index 0000000..fd8ebaf
--- /dev/null
+++ b/trace-viewer/third_party/v8/LICENSE.valgrind
@@ -0,0 +1,45 @@
+----------------------------------------------------------------
+
+Notice that the following BSD-style license applies to this one
+file (valgrind.h) only.  The rest of Valgrind is licensed under the
+terms of the GNU General Public License, version 2, unless
+otherwise indicated.  See the COPYING file in the source
+distribution for details.
+
+----------------------------------------------------------------
+
+This file is part of Valgrind, a dynamic binary instrumentation
+framework.
+
+Copyright (C) 2000-2007 Julian Seward.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. The origin of this software must not be misrepresented; you must 
+   not claim that you wrote the original software.  If you use this 
+   software in a product, an acknowledgment in the product 
+   documentation would be appreciated but is not required.
+
+3. Altered source versions must be plainly marked as such, and must
+   not be misrepresented as being the original software.
+
+4. The name of the author may not be used to endorse or promote 
+   products derived from this software without specific prior written 
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/trace-viewer/third_party/v8/README.chromium b/trace-viewer/third_party/v8/README.chromium
new file mode 100644
index 0000000..2d4931c
--- /dev/null
+++ b/trace-viewer/third_party/v8/README.chromium
@@ -0,0 +1,10 @@
+Name: Chrome d8 for executing javascript
+Short Name: d8
+URL: https://developers.google.com/v8/
+Version: 4.3.61
+License: BSD
+License File: LICENSE, LICENSE.v8, LICENSE.strongtalk, LICENSE.valgrind
+Security Critical: no
+Description: d8 binaries is used for executing trace-viewer's trace analyzing
+code.
+Local modifications: We ignore the source code & only keep the d8 binaries.
diff --git a/trace-viewer/third_party/v8/linux/x86_64/d8 b/trace-viewer/third_party/v8/linux/x86_64/d8
new file mode 100755
index 0000000..09ae15e
--- /dev/null
+++ b/trace-viewer/third_party/v8/linux/x86_64/d8
Binary files differ
diff --git a/trace-viewer/third_party/v8/mac/x86_64/d8 b/trace-viewer/third_party/v8/mac/x86_64/d8
new file mode 100755
index 0000000..733b794
--- /dev/null
+++ b/trace-viewer/third_party/v8/mac/x86_64/d8
Binary files differ
diff --git a/trace-viewer/trace_viewer.gyp b/trace-viewer/trace_viewer.gyp
index fc9366c..32c28f7 100644
--- a/trace-viewer/trace_viewer.gyp
+++ b/trace-viewer/trace_viewer.gyp
@@ -3,404 +3,9 @@
 # found in the LICENSE file.
 
 {
-  'variables': {
-    'tracing_css_files': [
-      'trace_viewer/base/ui/common.css',
-      'trace_viewer/base/ui/drag_handle.css',
-      'trace_viewer/base/ui/line_chart.css',
-      'trace_viewer/base/ui/list_view.css',
-      'trace_viewer/base/ui/mouse_mode_selector.css',
-      'trace_viewer/base/ui/pie_chart.css',
-      'trace_viewer/base/ui/sortable_table.css',
-      'trace_viewer/base/ui/sunburst_chart.css',
-      'trace_viewer/base/ui/tool_button.css',
-      'trace_viewer/core/analysis/analysis_results.css',
-      'trace_viewer/core/timeline_track_view.css',
-      'trace_viewer/core/timeline_view.css',
-      'trace_viewer/core/tracks/drawing_container.css',
-      'trace_viewer/core/tracks/heading_track.css',
-      'trace_viewer/core/tracks/object_instance_track.css',
-      'trace_viewer/core/tracks/process_track_base.css',
-      'trace_viewer/core/tracks/rect_track.css',
-      'trace_viewer/core/tracks/ruler_track.css',
-      'trace_viewer/core/tracks/spacing_track.css',
-      'trace_viewer/core/tracks/thread_track.css',
-      'trace_viewer/core/tracks/track.css',
-      'trace_viewer/extras/about_tracing/common.css',
-      'trace_viewer/extras/chrome/cc/display_item_view.css',
-      'trace_viewer/extras/chrome/cc/layer_picker.css',
-      'trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.css',
-      'trace_viewer/extras/chrome/cc/layer_view.css',
-      'trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.css',
-      'trace_viewer/extras/chrome/cc/picture_ops_chart_view.css',
-      'trace_viewer/extras/chrome/cc/picture_ops_list_view.css',
-      'trace_viewer/extras/chrome/cc/picture_view.css',
-      'trace_viewer/extras/chrome/gpu/state_view.css',
-      'trace_viewer/extras/system_stats/system_stats_instance_track.css',
-      'trace_viewer/extras/system_stats/system_stats_snapshot_view.css',
-      'trace_viewer/extras/tcmalloc/heap_instance_track.css',
-      'trace_viewer/extras/tcmalloc/tcmalloc_instance_view.css',
-      'trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.css',
-    ],
-    'tracing_js_html_files': [
-      'trace_viewer/base/base.html',
-      'trace_viewer/base/base64.html',
-      'trace_viewer/base/bbox2.html',
-      'trace_viewer/base/category_util.html',
-      'trace_viewer/base/color.html',
-      'trace_viewer/base/event_target.html',
-      'trace_viewer/base/events.html',
-      'trace_viewer/base/extension_registry.html',
-      'trace_viewer/base/extension_registry_base.html',
-      'trace_viewer/base/extension_registry_basic.html',
-      'trace_viewer/base/extension_registry_type_based.html',
-      'trace_viewer/base/gl_matrix.html',
-      'trace_viewer/base/guid.html',
-      'trace_viewer/base/interval_tree.html',
-      'trace_viewer/base/iteration_helpers.html',
-      'trace_viewer/base/key_event_manager.html',
-      'trace_viewer/base/polymer_utils.html',
-      'trace_viewer/base/properties.html',
-      'trace_viewer/base/quad.html',
-      'trace_viewer/base/raf.html',
-      'trace_viewer/base/range.html',
-      'trace_viewer/base/rect.html',
-      'trace_viewer/base/settings.html',
-      'trace_viewer/base/sorted_array_utils.html',
-      'trace_viewer/base/statistics.html',
-      'trace_viewer/base/task.html',
-      'trace_viewer/base/time.html',
-      'trace_viewer/base/ui.html',
-      'trace_viewer/base/ui/animation.html',
-      'trace_viewer/base/ui/animation_controller.html',
-      'trace_viewer/base/ui/camera.html',
-      'trace_viewer/base/ui/chart_base.html',
-      'trace_viewer/base/ui/color_legend.html',
-      'trace_viewer/base/ui/color_scheme.html',
-      'trace_viewer/base/ui/color_utils.html',
-      'trace_viewer/base/ui/container_that_decorates_its_children.html',
-      'trace_viewer/base/ui/d3.html',
-      'trace_viewer/base/ui/dom_helpers.html',
-      'trace_viewer/base/ui/drag_handle.html',
-      'trace_viewer/base/ui/dropdown.html',
-      'trace_viewer/base/ui/info_bar.html',
-      'trace_viewer/base/ui/info_bar_group.html',
-      'trace_viewer/base/ui/line_chart.html',
-      'trace_viewer/base/ui/list_view.html',
-      'trace_viewer/base/ui/mouse_mode_selector.html',
-      'trace_viewer/base/ui/mouse_tracker.html',
-      'trace_viewer/base/ui/overlay.html',
-      'trace_viewer/base/ui/pie_chart.html',
-      'trace_viewer/base/ui/quad_stack_view.html',
-      'trace_viewer/base/ui/sortable_table.html',
-      'trace_viewer/base/ui/sunburst_chart.html',
-      'trace_viewer/base/utils.html',
-      'trace_viewer/core/analysis/alert_sub_view.html',
-      'trace_viewer/core/analysis/analysis_link.html',
-      'trace_viewer/core/analysis/analysis_results.html',
-      'trace_viewer/core/analysis/analysis_sub_view.html',
-      'trace_viewer/core/analysis/analysis_view.html',
-      'trace_viewer/core/analysis/counter_sample_sub_view.html',
-      'trace_viewer/core/analysis/flow_classifier.html',
-      'trace_viewer/core/analysis/generic_object_view.html',
-      'trace_viewer/core/analysis/memory_dump_allocator_details_pane.html',
-      'trace_viewer/core/analysis/memory_dump_overview_pane.html',
-      'trace_viewer/core/analysis/memory_dump_sub_view_util.html',
-      'trace_viewer/core/analysis/memory_dump_view.html',
-      'trace_viewer/core/analysis/memory_dump_vm_regions_details_pane.html',
-      'trace_viewer/core/analysis/multi_async_slice_sub_view.html',
-      'trace_viewer/core/analysis/multi_cpu_slice_sub_view.html',
-      'trace_viewer/core/analysis/multi_event_details_table.html',
-      'trace_viewer/core/analysis/multi_event_sub_view.html',
-      'trace_viewer/core/analysis/multi_event_summary.html',
-      'trace_viewer/core/analysis/multi_event_summary_table.html',
-      'trace_viewer/core/analysis/multi_flow_event_sub_view.html',
-      'trace_viewer/core/analysis/multi_frame_sub_view.html',
-      'trace_viewer/core/analysis/multi_global_memory_dump_sub_view.html',
-      'trace_viewer/core/analysis/multi_instant_event_sub_view.html',
-      'trace_viewer/core/analysis/multi_interaction_record_sub_view.html',
-      'trace_viewer/core/analysis/multi_object_sub_view.html',
-      'trace_viewer/core/analysis/multi_process_memory_dump_sub_view.html',
-      'trace_viewer/core/analysis/multi_sample_sub_view.html',
-      'trace_viewer/core/analysis/multi_thread_slice_sub_view.html',
-      'trace_viewer/core/analysis/multi_thread_time_slice_sub_view.html',
-      'trace_viewer/core/analysis/object_instance_view.html',
-      'trace_viewer/core/analysis/object_snapshot_view.html',
-      'trace_viewer/core/analysis/related_flows.html',
-      'trace_viewer/core/analysis/selection_summary_table.html',
-      'trace_viewer/core/analysis/single_async_slice_sub_view.html',
-      'trace_viewer/core/analysis/single_cpu_slice_sub_view.html',
-      'trace_viewer/core/analysis/single_event_sub_view.html',
-      'trace_viewer/core/analysis/single_flow_event_sub_view.html',
-      'trace_viewer/core/analysis/single_frame_sub_view.html',
-      'trace_viewer/core/analysis/single_global_memory_dump_sub_view.html',
-      'trace_viewer/core/analysis/single_instant_event_sub_view.html',
-      'trace_viewer/core/analysis/single_interaction_record_sub_view.html',
-      'trace_viewer/core/analysis/single_object_instance_sub_view.html',
-      'trace_viewer/core/analysis/single_object_snapshot_sub_view.html',
-      'trace_viewer/core/analysis/single_process_memory_dump_sub_view.html',
-      'trace_viewer/core/analysis/single_sample_sub_view.html',
-      'trace_viewer/core/analysis/single_thread_slice_sub_view.html',
-      'trace_viewer/core/analysis/single_thread_time_slice_sub_view.html',
-      'trace_viewer/core/analysis/size_span.html',
-      'trace_viewer/core/analysis/stack_frame.html',
-      'trace_viewer/core/analysis/tab_view.html',
-      'trace_viewer/core/analysis/table_builder.html',
-      'trace_viewer/core/analysis/time_span.html',
-      'trace_viewer/core/analysis/time_stamp.html',
-      'trace_viewer/core/analysis/toggle_container.html',
-      'trace_viewer/core/analysis/util.html',
-      'trace_viewer/core/auditor.html',
-      'trace_viewer/core/brushing_state.html',
-      'trace_viewer/core/constants.html',
-      'trace_viewer/core/draw_helpers.html',
-      'trace_viewer/core/elided_cache.html',
-      'trace_viewer/core/event_presenter.html',
-      'trace_viewer/core/fast_rect_renderer.html',
-      'trace_viewer/core/favicons.html',
-      'trace_viewer/core/filter.html',
-      'trace_viewer/core/find_control.html',
-      'trace_viewer/core/find_controller.html',
-      'trace_viewer/core/importer/empty_importer.html',
-      'trace_viewer/core/importer/importer.html',
-      'trace_viewer/core/importer/simple_line_reader.html',
-      'trace_viewer/core/location.html',
-      'trace_viewer/core/scripting_control.html',
-      'trace_viewer/core/scripting_controller.html',
-      'trace_viewer/core/scripting_object.html',
-      'trace_viewer/core/selection.html',
-      'trace_viewer/core/selection_controller.html',
-      'trace_viewer/core/side_panel/side_panel.html',
-      'trace_viewer/core/side_panel/side_panel_container.html',
-      'trace_viewer/core/timeline_display_transform.html',
-      'trace_viewer/core/timeline_display_transform_animations.html',
-      'trace_viewer/core/timeline_interest_range.html',
-      'trace_viewer/core/timeline_track_view.html',
-      'trace_viewer/core/timeline_view.html',
-      'trace_viewer/core/timeline_viewport.html',
-      'trace_viewer/core/timing_tool.html',
-      'trace_viewer/core/trace_model/alert.html',
-      'trace_viewer/core/trace_model/annotation.html',
-      'trace_viewer/core/trace_model/async_slice.html',
-      'trace_viewer/core/trace_model/async_slice_group.html',
-      'trace_viewer/core/trace_model/attribute.html',
-      'trace_viewer/core/trace_model/comment_box_annotation.html',
-      'trace_viewer/core/trace_model/container_memory_dump.html',
-      'trace_viewer/core/trace_model/counter.html',
-      'trace_viewer/core/trace_model/counter_sample.html',
-      'trace_viewer/core/trace_model/counter_series.html',
-      'trace_viewer/core/trace_model/cpu.html',
-      'trace_viewer/core/trace_model/cpu_slice.html',
-      'trace_viewer/core/trace_model/event.html',
-      'trace_viewer/core/trace_model/event_container.html',
-      'trace_viewer/core/trace_model/event_info.html',
-      'trace_viewer/core/trace_model/flow_event.html',
-      'trace_viewer/core/trace_model/frame.html',
-      'trace_viewer/core/trace_model/global_memory_dump.html',
-      'trace_viewer/core/trace_model/instant_event.html',
-      'trace_viewer/core/trace_model/interaction_record.html',
-      'trace_viewer/core/trace_model/kernel.html',
-      'trace_viewer/core/trace_model/memory_allocator_dump.html',
-      'trace_viewer/core/trace_model/object_collection.html',
-      'trace_viewer/core/trace_model/object_instance.html',
-      'trace_viewer/core/trace_model/object_snapshot.html',
-      'trace_viewer/core/trace_model/process.html',
-      'trace_viewer/core/trace_model/process_base.html',
-      'trace_viewer/core/trace_model/process_memory_dump.html',
-      'trace_viewer/core/trace_model/proxy_selectable_item.html',
-      'trace_viewer/core/trace_model/rect_annotation.html',
-      'trace_viewer/core/trace_model/sample.html',
-      'trace_viewer/core/trace_model/selectable_item.html',
-      'trace_viewer/core/trace_model/selection_state.html',
-      'trace_viewer/core/trace_model/slice.html',
-      'trace_viewer/core/trace_model/slice_group.html',
-      'trace_viewer/core/trace_model/stack_frame.html',
-      'trace_viewer/core/trace_model/thread.html',
-      'trace_viewer/core/trace_model/thread_slice.html',
-      'trace_viewer/core/trace_model/thread_time_slice.html',
-      'trace_viewer/core/trace_model/time_to_object_instance_map.html',
-      'trace_viewer/core/trace_model/timed_event.html',
-      'trace_viewer/core/trace_model/trace_model.html',
-      'trace_viewer/core/trace_model/trace_model_settings.html',
-      'trace_viewer/core/trace_model/x_marker_annotation.html',
-      'trace_viewer/core/tracks/alert_track.html',
-      'trace_viewer/core/tracks/annotation_view.html',
-      'trace_viewer/core/tracks/async_slice_group_track.html',
-      'trace_viewer/core/tracks/chart_axis.html',
-      'trace_viewer/core/tracks/chart_point.html',
-      'trace_viewer/core/tracks/chart_series.html',
-      'trace_viewer/core/tracks/chart_track.html',
-      'trace_viewer/core/tracks/chart_transform.html',
-      'trace_viewer/core/tracks/comment_box_annotation_view.html',
-      'trace_viewer/core/tracks/container_track.html',
-      'trace_viewer/core/tracks/counter_track.html',
-      'trace_viewer/core/tracks/cpu_track.html',
-      'trace_viewer/core/tracks/drawing_container.html',
-      'trace_viewer/core/tracks/frame_track.html',
-      'trace_viewer/core/tracks/global_memory_dump_track.html',
-      'trace_viewer/core/tracks/heading_track.html',
-      'trace_viewer/core/tracks/highlighter.html',
-      'trace_viewer/core/tracks/kernel_track.html',
-      'trace_viewer/core/tracks/letter_dot_track.html',
-      'trace_viewer/core/tracks/memory_dump_track_util.html',
-      'trace_viewer/core/tracks/multi_row_track.html',
-      'trace_viewer/core/tracks/object_instance_group_track.html',
-      'trace_viewer/core/tracks/object_instance_track.html',
-      'trace_viewer/core/tracks/process_memory_dump_track.html',
-      'trace_viewer/core/tracks/process_summary_track.html',
-      'trace_viewer/core/tracks/process_track.html',
-      'trace_viewer/core/tracks/process_track_base.html',
-      'trace_viewer/core/tracks/rect_annotation_view.html',
-      'trace_viewer/core/tracks/rect_track.html',
-      'trace_viewer/core/tracks/ruler_track.html',
-      'trace_viewer/core/tracks/sample_track.html',
-      'trace_viewer/core/tracks/slice_group_track.html',
-      'trace_viewer/core/tracks/slice_track.html',
-      'trace_viewer/core/tracks/spacing_track.html',
-      'trace_viewer/core/tracks/stacked_bars_track.html',
-      'trace_viewer/core/tracks/thread_track.html',
-      'trace_viewer/core/tracks/trace_model_track.html',
-      'trace_viewer/core/tracks/track.html',
-      'trace_viewer/core/tracks/x_marker_annotation_view.html',
-      'trace_viewer/core/ui_state.html',
-      'trace_viewer/extras/about_tracing/about_tracing.html',
-      'trace_viewer/extras/about_tracing/inspector_connection.html',
-      'trace_viewer/extras/about_tracing/inspector_tracing_controller_client.html',
-      'trace_viewer/extras/about_tracing/profiling_view.html',
-      'trace_viewer/extras/about_tracing/record_and_capture_controller.html',
-      'trace_viewer/extras/about_tracing/record_selection_dialog.html',
-      'trace_viewer/extras/about_tracing/tracing_controller_client.html',
-      'trace_viewer/extras/about_tracing/xhr_based_tracing_controller_client.html',
-      'trace_viewer/extras/analysis/sampling_summary.html',
-      'trace_viewer/extras/audits/android_app.html',
-      'trace_viewer/extras/audits/android_auditor.html',
-      'trace_viewer/extras/audits/android_model_helper.html',
-      'trace_viewer/extras/audits/android_surface_flinger.html',
-      'trace_viewer/extras/audits/utils.html',
-      'trace_viewer/extras/chrome/cc/cc.html',
-      'trace_viewer/extras/chrome/cc/constants.html',
-      'trace_viewer/extras/chrome/cc/debug_colors.html',
-      'trace_viewer/extras/chrome/cc/display_item_debugger.html',
-      'trace_viewer/extras/chrome/cc/display_item_list.html',
-      'trace_viewer/extras/chrome/cc/display_item_view.html',
-      'trace_viewer/extras/chrome/cc/input_latency_async_slice.html',
-      'trace_viewer/extras/chrome/cc/layer_impl.html',
-      'trace_viewer/extras/chrome/cc/layer_picker.html',
-      'trace_viewer/extras/chrome/cc/layer_tree_host_impl.html',
-      'trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.html',
-      'trace_viewer/extras/chrome/cc/layer_tree_impl.html',
-      'trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view.html',
-      'trace_viewer/extras/chrome/cc/layer_view.html',
-      'trace_viewer/extras/chrome/cc/picture.html',
-      'trace_viewer/extras/chrome/cc/picture_as_image_data.html',
-      'trace_viewer/extras/chrome/cc/picture_debugger.html',
-      'trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.html',
-      'trace_viewer/extras/chrome/cc/picture_ops_chart_view.html',
-      'trace_viewer/extras/chrome/cc/picture_ops_list_view.html',
-      'trace_viewer/extras/chrome/cc/picture_view.html',
-      'trace_viewer/extras/chrome/cc/raster_task.html',
-      'trace_viewer/extras/chrome/cc/raster_task_selection.html',
-      'trace_viewer/extras/chrome/cc/raster_task_view.html',
-      'trace_viewer/extras/chrome/cc/region.html',
-      'trace_viewer/extras/chrome/cc/render_pass.html',
-      'trace_viewer/extras/chrome/cc/selection.html',
-      'trace_viewer/extras/chrome/cc/tile.html',
-      'trace_viewer/extras/chrome/cc/tile_coverage_rect.html',
-      'trace_viewer/extras/chrome/cc/tile_view.html',
-      'trace_viewer/extras/chrome/cc/util.html',
-      'trace_viewer/extras/chrome/chrome_auditor.html',
-      'trace_viewer/extras/chrome/chrome_browser_helper.html',
-      'trace_viewer/extras/chrome/chrome_model_helper.html',
-      'trace_viewer/extras/chrome/chrome_process_helper.html',
-      'trace_viewer/extras/chrome/chrome_renderer_helper.html',
-      'trace_viewer/extras/chrome/gpu/gpu.html',
-      'trace_viewer/extras/chrome/gpu/gpu_async_slice.html',
-      'trace_viewer/extras/chrome/gpu/state.html',
-      'trace_viewer/extras/chrome/gpu/state_view.html',
-      'trace_viewer/extras/chrome_config.html',
-      'trace_viewer/extras/full_config.html',
-      'trace_viewer/extras/highlighter/vsync_highlighter.html',
-      'trace_viewer/extras/importer/battor_importer.html',
-      'trace_viewer/extras/importer/ddms_importer.html',
-      'trace_viewer/extras/importer/etw/etw_importer.html',
-      'trace_viewer/extras/importer/etw/eventtrace_parser.html',
-      'trace_viewer/extras/importer/etw/parser.html',
-      'trace_viewer/extras/importer/etw/process_parser.html',
-      'trace_viewer/extras/importer/etw/thread_parser.html',
-      'trace_viewer/extras/importer/gzip_importer.html',
-      'trace_viewer/extras/importer/jszip.html',
-      'trace_viewer/extras/importer/linux_perf/android_parser.html',
-      'trace_viewer/extras/importer/linux_perf/bus_parser.html',
-      'trace_viewer/extras/importer/linux_perf/clock_parser.html',
-      'trace_viewer/extras/importer/linux_perf/cpufreq_parser.html',
-      'trace_viewer/extras/importer/linux_perf/disk_parser.html',
-      'trace_viewer/extras/importer/linux_perf/drm_parser.html',
-      'trace_viewer/extras/importer/linux_perf/exynos_parser.html',
-      'trace_viewer/extras/importer/linux_perf/ftrace_importer.html',
-      'trace_viewer/extras/importer/linux_perf/gesture_parser.html',
-      'trace_viewer/extras/importer/linux_perf/i915_parser.html',
-      'trace_viewer/extras/importer/linux_perf/irq_parser.html',
-      'trace_viewer/extras/importer/linux_perf/kfunc_parser.html',
-      'trace_viewer/extras/importer/linux_perf/mali_parser.html',
-      'trace_viewer/extras/importer/linux_perf/memreclaim_parser.html',
-      'trace_viewer/extras/importer/linux_perf/parser.html',
-      'trace_viewer/extras/importer/linux_perf/power_parser.html',
-      'trace_viewer/extras/importer/linux_perf/regulator_parser.html',
-      'trace_viewer/extras/importer/linux_perf/sched_parser.html',
-      'trace_viewer/extras/importer/linux_perf/sync_parser.html',
-      'trace_viewer/extras/importer/linux_perf/workqueue_parser.html',
-      'trace_viewer/extras/importer/trace2html_importer.html',
-      'trace_viewer/extras/importer/trace_event_importer.html',
-      'trace_viewer/extras/importer/v8/codemap.html',
-      'trace_viewer/extras/importer/v8/log_reader.html',
-      'trace_viewer/extras/importer/v8/splaytree.html',
-      'trace_viewer/extras/importer/v8/v8_log_importer.html',
-      'trace_viewer/extras/importer/zip_importer.html',
-      'trace_viewer/extras/lean_config.html',
-      'trace_viewer/extras/net/net.html',
-      'trace_viewer/extras/net/net_async_slice.html',
-      'trace_viewer/extras/rail/rail_interaction_record.html',
-      'trace_viewer/extras/rail/rail_ir_finder.html',
-      'trace_viewer/extras/side_panel/alerts_side_panel.html',
-      'trace_viewer/extras/side_panel/input_latency.html',
-      'trace_viewer/extras/side_panel/time_summary.html',
-      'trace_viewer/extras/system_stats/system_stats.html',
-      'trace_viewer/extras/system_stats/system_stats_instance_track.html',
-      'trace_viewer/extras/system_stats/system_stats_snapshot.html',
-      'trace_viewer/extras/system_stats/system_stats_snapshot_view.html',
-      'trace_viewer/extras/systrace_config.html',
-      'trace_viewer/extras/tcmalloc/heap.html',
-      'trace_viewer/extras/tcmalloc/heap_instance_track.html',
-      'trace_viewer/extras/tcmalloc/tcmalloc.html',
-      'trace_viewer/extras/tcmalloc/tcmalloc_instance_view.html',
-      'trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.html',
-      'trace_viewer/extras/tquery/context.html',
-      'trace_viewer/extras/tquery/filter.html',
-      'trace_viewer/extras/tquery/filter_all_of.html',
-      'trace_viewer/extras/tquery/filter_any_of.html',
-      'trace_viewer/extras/tquery/filter_has_ancestor.html',
-      'trace_viewer/extras/tquery/filter_has_duration.html',
-      'trace_viewer/extras/tquery/filter_has_title.html',
-      'trace_viewer/extras/tquery/filter_is_top_level.html',
-      'trace_viewer/extras/tquery/tquery.html',
-      'trace_viewer/trace_viewer.html',
-    ],
-    'tracing_img_files': [
-      'trace_viewer/base/images/chrome-left.png',
-      'trace_viewer/base/images/chrome-mid.png',
-      'trace_viewer/base/images/chrome-right.png',
-      'trace_viewer/base/images/ui-states.png',
-      'trace_viewer/extras/chrome/cc/images/input-event.png',
-      'trace_viewer/extras/chrome/gpu/images/checkerboard.png',
-      'trace_viewer/extras/tcmalloc/images/collapse.png',
-      'trace_viewer/extras/tcmalloc/images/expand.png',
-    ],
-    'tracing_files': [
-      '<@(tracing_css_files)',
-      '<@(tracing_js_html_files)',
-      '<@(tracing_img_files)',
-    ],
-  },
+  'includes': [
+    'trace_viewer.gypi',
+  ],
   'targets': [
     {
       'target_name': 'generate_about_tracing',
diff --git a/trace-viewer/trace_viewer.gypi b/trace-viewer/trace_viewer.gypi
new file mode 100644
index 0000000..39cf51b
--- /dev/null
+++ b/trace-viewer/trace_viewer.gypi
@@ -0,0 +1,416 @@
+# Copyright (c) 2015 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.
+
+{
+  'variables': {
+    'tracing_css_files': [
+      'trace_viewer/base/ui/common.css',
+      'trace_viewer/base/ui/drag_handle.css',
+      'trace_viewer/base/ui/line_chart.css',
+      'trace_viewer/base/ui/list_view.css',
+      'trace_viewer/base/ui/mouse_mode_selector.css',
+      'trace_viewer/base/ui/pie_chart.css',
+      'trace_viewer/base/ui/sortable_table.css',
+      'trace_viewer/base/ui/sunburst_chart.css',
+      'trace_viewer/base/ui/tool_button.css',
+      'trace_viewer/core/analysis/analysis_results.css',
+      'trace_viewer/core/timeline_track_view.css',
+      'trace_viewer/core/timeline_view.css',
+      'trace_viewer/core/tracks/drawing_container.css',
+      'trace_viewer/core/tracks/heading_track.css',
+      'trace_viewer/core/tracks/object_instance_track.css',
+      'trace_viewer/core/tracks/process_track_base.css',
+      'trace_viewer/core/tracks/rect_track.css',
+      'trace_viewer/core/tracks/ruler_track.css',
+      'trace_viewer/core/tracks/spacing_track.css',
+      'trace_viewer/core/tracks/thread_track.css',
+      'trace_viewer/core/tracks/track.css',
+      'trace_viewer/extras/about_tracing/common.css',
+      'trace_viewer/extras/chrome/cc/display_item_view.css',
+      'trace_viewer/extras/chrome/cc/layer_picker.css',
+      'trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.css',
+      'trace_viewer/extras/chrome/cc/layer_view.css',
+      'trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.css',
+      'trace_viewer/extras/chrome/cc/picture_ops_chart_view.css',
+      'trace_viewer/extras/chrome/cc/picture_ops_list_view.css',
+      'trace_viewer/extras/chrome/cc/picture_view.css',
+      'trace_viewer/extras/chrome/gpu/state_view.css',
+      'trace_viewer/extras/system_stats/system_stats_instance_track.css',
+      'trace_viewer/extras/system_stats/system_stats_snapshot_view.css',
+      'trace_viewer/extras/tcmalloc/heap_instance_track.css',
+      'trace_viewer/extras/tcmalloc/tcmalloc_instance_view.css',
+      'trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.css',
+    ],
+    'tracing_js_html_files': [
+      'trace_viewer/base/base.html',
+      'trace_viewer/base/base64.html',
+      'trace_viewer/base/bbox2.html',
+      'trace_viewer/base/category_util.html',
+      'trace_viewer/base/color.html',
+      'trace_viewer/base/deep_utils.html',
+      'trace_viewer/base/event_target.html',
+      'trace_viewer/base/events.html',
+      'trace_viewer/base/extension_registry.html',
+      'trace_viewer/base/extension_registry_base.html',
+      'trace_viewer/base/extension_registry_basic.html',
+      'trace_viewer/base/extension_registry_type_based.html',
+      'trace_viewer/base/guid.html',
+      'trace_viewer/base/interval_tree.html',
+      'trace_viewer/base/iteration_helpers.html',
+      'trace_viewer/base/key_event_manager.html',
+      'trace_viewer/base/math.html',
+      'trace_viewer/base/polymer_utils.html',
+      'trace_viewer/base/properties.html',
+      'trace_viewer/base/quad.html',
+      'trace_viewer/base/raf.html',
+      'trace_viewer/base/range.html',
+      'trace_viewer/base/range_utils.html',
+      'trace_viewer/base/rect.html',
+      'trace_viewer/base/settings.html',
+      'trace_viewer/base/sorted_array_utils.html',
+      'trace_viewer/base/statistics.html',
+      'trace_viewer/base/task.html',
+      'trace_viewer/base/ui.html',
+      'trace_viewer/base/ui/animation.html',
+      'trace_viewer/base/ui/animation_controller.html',
+      'trace_viewer/base/ui/camera.html',
+      'trace_viewer/base/ui/chart_base.html',
+      'trace_viewer/base/ui/color_legend.html',
+      'trace_viewer/base/ui/color_scheme.html',
+      'trace_viewer/base/ui/color_utils.html',
+      'trace_viewer/base/ui/container_that_decorates_its_children.html',
+      'trace_viewer/base/ui/d3.html',
+      'trace_viewer/base/ui/dom_helpers.html',
+      'trace_viewer/base/ui/drag_handle.html',
+      'trace_viewer/base/ui/dropdown.html',
+      'trace_viewer/base/ui/info_bar.html',
+      'trace_viewer/base/ui/info_bar_group.html',
+      'trace_viewer/base/ui/line_chart.html',
+      'trace_viewer/base/ui/list_view.html',
+      'trace_viewer/base/ui/mouse_mode_selector.html',
+      'trace_viewer/base/ui/mouse_tracker.html',
+      'trace_viewer/base/ui/overlay.html',
+      'trace_viewer/base/ui/pie_chart.html',
+      'trace_viewer/base/ui/quad_stack_view.html',
+      'trace_viewer/base/ui/sortable_table.html',
+      'trace_viewer/base/ui/sunburst_chart.html',
+      'trace_viewer/base/ui/table.html',
+      'trace_viewer/base/units/size_in_bytes.html',
+      'trace_viewer/base/units/size_in_bytes_span.html',
+      'trace_viewer/base/units/time.html',
+      'trace_viewer/base/units/time_duration.html',
+      'trace_viewer/base/units/time_duration_span.html',
+      'trace_viewer/base/units/time_stamp.html',
+      'trace_viewer/base/units/time_stamp_span.html',
+      'trace_viewer/base/units/util.html',
+      'trace_viewer/base/utils.html',
+      'trace_viewer/core/analysis/alert_sub_view.html',
+      'trace_viewer/core/analysis/analysis_link.html',
+      'trace_viewer/core/analysis/analysis_results.html',
+      'trace_viewer/core/analysis/analysis_sub_view.html',
+      'trace_viewer/core/analysis/analysis_view.html',
+      'trace_viewer/core/analysis/counter_sample_sub_view.html',
+      'trace_viewer/core/analysis/flow_classifier.html',
+      'trace_viewer/core/analysis/generic_object_view.html',
+      'trace_viewer/core/analysis/memory_dump_allocator_details_pane.html',
+      'trace_viewer/core/analysis/memory_dump_overview_pane.html',
+      'trace_viewer/core/analysis/memory_dump_sub_view_util.html',
+      'trace_viewer/core/analysis/memory_dump_view.html',
+      'trace_viewer/core/analysis/memory_dump_vm_regions_details_pane.html',
+      'trace_viewer/core/analysis/multi_async_slice_sub_view.html',
+      'trace_viewer/core/analysis/multi_cpu_slice_sub_view.html',
+      'trace_viewer/core/analysis/multi_event_details_table.html',
+      'trace_viewer/core/analysis/multi_event_sub_view.html',
+      'trace_viewer/core/analysis/multi_event_summary.html',
+      'trace_viewer/core/analysis/multi_event_summary_table.html',
+      'trace_viewer/core/analysis/multi_flow_event_sub_view.html',
+      'trace_viewer/core/analysis/multi_frame_sub_view.html',
+      'trace_viewer/core/analysis/multi_global_memory_dump_sub_view.html',
+      'trace_viewer/core/analysis/multi_instant_event_sub_view.html',
+      'trace_viewer/core/analysis/multi_interaction_record_sub_view.html',
+      'trace_viewer/core/analysis/multi_object_sub_view.html',
+      'trace_viewer/core/analysis/multi_process_memory_dump_sub_view.html',
+      'trace_viewer/core/analysis/multi_sample_sub_view.html',
+      'trace_viewer/core/analysis/multi_thread_slice_sub_view.html',
+      'trace_viewer/core/analysis/multi_thread_time_slice_sub_view.html',
+      'trace_viewer/core/analysis/object_instance_view.html',
+      'trace_viewer/core/analysis/object_snapshot_view.html',
+      'trace_viewer/core/analysis/related_events.html',
+      'trace_viewer/core/analysis/selection_summary_table.html',
+      'trace_viewer/core/analysis/single_async_slice_sub_view.html',
+      'trace_viewer/core/analysis/single_cpu_slice_sub_view.html',
+      'trace_viewer/core/analysis/single_event_sub_view.html',
+      'trace_viewer/core/analysis/single_flow_event_sub_view.html',
+      'trace_viewer/core/analysis/single_frame_sub_view.html',
+      'trace_viewer/core/analysis/single_global_memory_dump_sub_view.html',
+      'trace_viewer/core/analysis/single_instant_event_sub_view.html',
+      'trace_viewer/core/analysis/single_interaction_record_sub_view.html',
+      'trace_viewer/core/analysis/single_object_instance_sub_view.html',
+      'trace_viewer/core/analysis/single_object_snapshot_sub_view.html',
+      'trace_viewer/core/analysis/single_process_memory_dump_sub_view.html',
+      'trace_viewer/core/analysis/single_sample_sub_view.html',
+      'trace_viewer/core/analysis/single_thread_slice_sub_view.html',
+      'trace_viewer/core/analysis/single_thread_time_slice_sub_view.html',
+      'trace_viewer/core/analysis/stack_frame.html',
+      'trace_viewer/core/analysis/tab_view.html',
+      'trace_viewer/core/auditor.html',
+      'trace_viewer/core/brushing_state.html',
+      'trace_viewer/core/constants.html',
+      'trace_viewer/core/draw_helpers.html',
+      'trace_viewer/core/elided_cache.html',
+      'trace_viewer/core/event_presenter.html',
+      'trace_viewer/core/fast_rect_renderer.html',
+      'trace_viewer/core/favicons.html',
+      'trace_viewer/core/filter.html',
+      'trace_viewer/core/find_control.html',
+      'trace_viewer/core/find_controller.html',
+      'trace_viewer/core/location.html',
+      'trace_viewer/core/scripting_control.html',
+      'trace_viewer/core/scripting_controller.html',
+      'trace_viewer/core/scripting_object.html',
+      'trace_viewer/core/selection.html',
+      'trace_viewer/core/selection_controller.html',
+      'trace_viewer/core/side_panel/side_panel.html',
+      'trace_viewer/core/side_panel/side_panel_container.html',
+      'trace_viewer/core/timeline_display_transform.html',
+      'trace_viewer/core/timeline_display_transform_animations.html',
+      'trace_viewer/core/timeline_interest_range.html',
+      'trace_viewer/core/timeline_track_view.html',
+      'trace_viewer/core/timeline_view.html',
+      'trace_viewer/core/timeline_viewport.html',
+      'trace_viewer/core/timing_tool.html',
+      'trace_viewer/core/tracks/alert_track.html',
+      'trace_viewer/core/tracks/annotation_view.html',
+      'trace_viewer/core/tracks/async_slice_group_track.html',
+      'trace_viewer/core/tracks/chart_axis.html',
+      'trace_viewer/core/tracks/chart_point.html',
+      'trace_viewer/core/tracks/chart_series.html',
+      'trace_viewer/core/tracks/chart_track.html',
+      'trace_viewer/core/tracks/chart_transform.html',
+      'trace_viewer/core/tracks/comment_box_annotation_view.html',
+      'trace_viewer/core/tracks/container_track.html',
+      'trace_viewer/core/tracks/counter_track.html',
+      'trace_viewer/core/tracks/cpu_track.html',
+      'trace_viewer/core/tracks/drawing_container.html',
+      'trace_viewer/core/tracks/frame_track.html',
+      'trace_viewer/core/tracks/global_memory_dump_track.html',
+      'trace_viewer/core/tracks/heading_track.html',
+      'trace_viewer/core/tracks/highlighter.html',
+      'trace_viewer/core/tracks/kernel_track.html',
+      'trace_viewer/core/tracks/letter_dot_track.html',
+      'trace_viewer/core/tracks/memory_dump_track_util.html',
+      'trace_viewer/core/tracks/model_track.html',
+      'trace_viewer/core/tracks/multi_row_track.html',
+      'trace_viewer/core/tracks/object_instance_group_track.html',
+      'trace_viewer/core/tracks/object_instance_track.html',
+      'trace_viewer/core/tracks/process_memory_dump_track.html',
+      'trace_viewer/core/tracks/process_summary_track.html',
+      'trace_viewer/core/tracks/process_track.html',
+      'trace_viewer/core/tracks/process_track_base.html',
+      'trace_viewer/core/tracks/rect_annotation_view.html',
+      'trace_viewer/core/tracks/rect_track.html',
+      'trace_viewer/core/tracks/ruler_track.html',
+      'trace_viewer/core/tracks/sample_track.html',
+      'trace_viewer/core/tracks/slice_group_track.html',
+      'trace_viewer/core/tracks/slice_track.html',
+      'trace_viewer/core/tracks/spacing_track.html',
+      'trace_viewer/core/tracks/stacked_bars_track.html',
+      'trace_viewer/core/tracks/thread_track.html',
+      'trace_viewer/core/tracks/track.html',
+      'trace_viewer/core/tracks/x_marker_annotation_view.html',
+      'trace_viewer/core/ui_state.html',
+      'trace_viewer/extras/about_tracing/about_tracing.html',
+      'trace_viewer/extras/about_tracing/inspector_connection.html',
+      'trace_viewer/extras/about_tracing/inspector_tracing_controller_client.html',
+      'trace_viewer/extras/about_tracing/profiling_view.html',
+      'trace_viewer/extras/about_tracing/record_and_capture_controller.html',
+      'trace_viewer/extras/about_tracing/record_selection_dialog.html',
+      'trace_viewer/extras/about_tracing/tracing_controller_client.html',
+      'trace_viewer/extras/about_tracing/xhr_based_tracing_controller_client.html',
+      'trace_viewer/extras/analysis/sampling_summary.html',
+      'trace_viewer/extras/android/android_app.html',
+      'trace_viewer/extras/android/android_auditor.html',
+      'trace_viewer/extras/android/android_model_helper.html',
+      'trace_viewer/extras/android/android_surface_flinger.html',
+      'trace_viewer/extras/chrome/cc/cc.html',
+      'trace_viewer/extras/chrome/cc/constants.html',
+      'trace_viewer/extras/chrome/cc/debug_colors.html',
+      'trace_viewer/extras/chrome/cc/display_item_debugger.html',
+      'trace_viewer/extras/chrome/cc/display_item_list.html',
+      'trace_viewer/extras/chrome/cc/display_item_view.html',
+      'trace_viewer/extras/chrome/cc/input_latency_async_slice.html',
+      'trace_viewer/extras/chrome/cc/layer_impl.html',
+      'trace_viewer/extras/chrome/cc/layer_picker.html',
+      'trace_viewer/extras/chrome/cc/layer_tree_host_impl.html',
+      'trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.html',
+      'trace_viewer/extras/chrome/cc/layer_tree_impl.html',
+      'trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view.html',
+      'trace_viewer/extras/chrome/cc/layer_view.html',
+      'trace_viewer/extras/chrome/cc/picture.html',
+      'trace_viewer/extras/chrome/cc/picture_as_image_data.html',
+      'trace_viewer/extras/chrome/cc/picture_debugger.html',
+      'trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.html',
+      'trace_viewer/extras/chrome/cc/picture_ops_chart_view.html',
+      'trace_viewer/extras/chrome/cc/picture_ops_list_view.html',
+      'trace_viewer/extras/chrome/cc/picture_view.html',
+      'trace_viewer/extras/chrome/cc/raster_task.html',
+      'trace_viewer/extras/chrome/cc/raster_task_selection.html',
+      'trace_viewer/extras/chrome/cc/raster_task_view.html',
+      'trace_viewer/extras/chrome/cc/region.html',
+      'trace_viewer/extras/chrome/cc/render_pass.html',
+      'trace_viewer/extras/chrome/cc/selection.html',
+      'trace_viewer/extras/chrome/cc/tile.html',
+      'trace_viewer/extras/chrome/cc/tile_coverage_rect.html',
+      'trace_viewer/extras/chrome/cc/tile_view.html',
+      'trace_viewer/extras/chrome/cc/util.html',
+      'trace_viewer/extras/chrome/chrome_auditor.html',
+      'trace_viewer/extras/chrome/chrome_browser_helper.html',
+      'trace_viewer/extras/chrome/chrome_model_helper.html',
+      'trace_viewer/extras/chrome/chrome_process_helper.html',
+      'trace_viewer/extras/chrome/chrome_renderer_helper.html',
+      'trace_viewer/extras/chrome/gpu/gpu.html',
+      'trace_viewer/extras/chrome/gpu/gpu_async_slice.html',
+      'trace_viewer/extras/chrome/gpu/state.html',
+      'trace_viewer/extras/chrome/gpu/state_view.html',
+      'trace_viewer/extras/chrome_config.html',
+      'trace_viewer/extras/full_config.html',
+      'trace_viewer/extras/highlighter/vsync_highlighter.html',
+      'trace_viewer/extras/importer/battor_importer.html',
+      'trace_viewer/extras/importer/ddms_importer.html',
+      'trace_viewer/extras/importer/etw/etw_importer.html',
+      'trace_viewer/extras/importer/etw/eventtrace_parser.html',
+      'trace_viewer/extras/importer/etw/parser.html',
+      'trace_viewer/extras/importer/etw/process_parser.html',
+      'trace_viewer/extras/importer/etw/thread_parser.html',
+      'trace_viewer/extras/importer/gzip_importer.html',
+      'trace_viewer/extras/importer/jszip.html',
+      'trace_viewer/extras/importer/linux_perf/android_parser.html',
+      'trace_viewer/extras/importer/linux_perf/bus_parser.html',
+      'trace_viewer/extras/importer/linux_perf/clock_parser.html',
+      'trace_viewer/extras/importer/linux_perf/cpufreq_parser.html',
+      'trace_viewer/extras/importer/linux_perf/disk_parser.html',
+      'trace_viewer/extras/importer/linux_perf/drm_parser.html',
+      'trace_viewer/extras/importer/linux_perf/exynos_parser.html',
+      'trace_viewer/extras/importer/linux_perf/ftrace_importer.html',
+      'trace_viewer/extras/importer/linux_perf/gesture_parser.html',
+      'trace_viewer/extras/importer/linux_perf/i915_parser.html',
+      'trace_viewer/extras/importer/linux_perf/irq_parser.html',
+      'trace_viewer/extras/importer/linux_perf/kfunc_parser.html',
+      'trace_viewer/extras/importer/linux_perf/mali_parser.html',
+      'trace_viewer/extras/importer/linux_perf/memreclaim_parser.html',
+      'trace_viewer/extras/importer/linux_perf/parser.html',
+      'trace_viewer/extras/importer/linux_perf/power_parser.html',
+      'trace_viewer/extras/importer/linux_perf/regulator_parser.html',
+      'trace_viewer/extras/importer/linux_perf/sched_parser.html',
+      'trace_viewer/extras/importer/linux_perf/sync_parser.html',
+      'trace_viewer/extras/importer/linux_perf/workqueue_parser.html',
+      'trace_viewer/extras/importer/trace2html_importer.html',
+      'trace_viewer/extras/importer/trace_event_importer.html',
+      'trace_viewer/extras/importer/v8/codemap.html',
+      'trace_viewer/extras/importer/v8/log_reader.html',
+      'trace_viewer/extras/importer/v8/splaytree.html',
+      'trace_viewer/extras/importer/v8/v8_log_importer.html',
+      'trace_viewer/extras/importer/zip_importer.html',
+      'trace_viewer/extras/lean_config.html',
+      'trace_viewer/extras/net/net.html',
+      'trace_viewer/extras/net/net_async_slice.html',
+      'trace_viewer/extras/rail/animation_interaction_record.html',
+      'trace_viewer/extras/rail/idle_interaction_record.html',
+      'trace_viewer/extras/rail/load_interaction_record.html',
+      'trace_viewer/extras/rail/rail_interaction_record.html',
+      'trace_viewer/extras/rail/rail_ir_finder.html',
+      'trace_viewer/extras/rail/rail_score.html',
+      'trace_viewer/extras/rail/rail_score_side_panel.html',
+      'trace_viewer/extras/rail/rail_score_span.html',
+      'trace_viewer/extras/rail/response_interaction_record.html',
+      'trace_viewer/extras/side_panel/alerts_side_panel.html',
+      'trace_viewer/extras/side_panel/input_latency_side_panel.html',
+      'trace_viewer/extras/side_panel/time_summary_side_panel.html',
+      'trace_viewer/extras/system_stats/system_stats.html',
+      'trace_viewer/extras/system_stats/system_stats_instance_track.html',
+      'trace_viewer/extras/system_stats/system_stats_snapshot.html',
+      'trace_viewer/extras/system_stats/system_stats_snapshot_view.html',
+      'trace_viewer/extras/systrace_config.html',
+      'trace_viewer/extras/tcmalloc/heap.html',
+      'trace_viewer/extras/tcmalloc/heap_instance_track.html',
+      'trace_viewer/extras/tcmalloc/tcmalloc.html',
+      'trace_viewer/extras/tcmalloc/tcmalloc_instance_view.html',
+      'trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.html',
+      'trace_viewer/extras/tquery/context.html',
+      'trace_viewer/extras/tquery/filter.html',
+      'trace_viewer/extras/tquery/filter_all_of.html',
+      'trace_viewer/extras/tquery/filter_any_of.html',
+      'trace_viewer/extras/tquery/filter_has_ancestor.html',
+      'trace_viewer/extras/tquery/filter_has_duration.html',
+      'trace_viewer/extras/tquery/filter_has_title.html',
+      'trace_viewer/extras/tquery/filter_is_top_level.html',
+      'trace_viewer/extras/tquery/tquery.html',
+      'trace_viewer/importer/empty_importer.html',
+      'trace_viewer/importer/importer.html',
+      'trace_viewer/importer/simple_line_reader.html',
+      'trace_viewer/model/alert.html',
+      'trace_viewer/model/annotation.html',
+      'trace_viewer/model/async_slice.html',
+      'trace_viewer/model/async_slice_group.html',
+      'trace_viewer/model/attribute.html',
+      'trace_viewer/model/comment_box_annotation.html',
+      'trace_viewer/model/container_memory_dump.html',
+      'trace_viewer/model/counter.html',
+      'trace_viewer/model/counter_sample.html',
+      'trace_viewer/model/counter_series.html',
+      'trace_viewer/model/cpu.html',
+      'trace_viewer/model/cpu_slice.html',
+      'trace_viewer/model/device.html',
+      'trace_viewer/model/event.html',
+      'trace_viewer/model/event_container.html',
+      'trace_viewer/model/event_info.html',
+      'trace_viewer/model/flow_event.html',
+      'trace_viewer/model/frame.html',
+      'trace_viewer/model/global_memory_dump.html',
+      'trace_viewer/model/instant_event.html',
+      'trace_viewer/model/interaction_record.html',
+      'trace_viewer/model/kernel.html',
+      'trace_viewer/model/memory_allocator_dump.html',
+      'trace_viewer/model/model.html',
+      'trace_viewer/model/model_indices.html',
+      'trace_viewer/model/model_settings.html',
+      'trace_viewer/model/object_collection.html',
+      'trace_viewer/model/object_instance.html',
+      'trace_viewer/model/object_snapshot.html',
+      'trace_viewer/model/process.html',
+      'trace_viewer/model/process_base.html',
+      'trace_viewer/model/process_memory_dump.html',
+      'trace_viewer/model/proxy_selectable_item.html',
+      'trace_viewer/model/rect_annotation.html',
+      'trace_viewer/model/sample.html',
+      'trace_viewer/model/selectable_item.html',
+      'trace_viewer/model/selection_state.html',
+      'trace_viewer/model/slice.html',
+      'trace_viewer/model/slice_group.html',
+      'trace_viewer/model/stack_frame.html',
+      'trace_viewer/model/thread.html',
+      'trace_viewer/model/thread_slice.html',
+      'trace_viewer/model/thread_time_slice.html',
+      'trace_viewer/model/time_to_object_instance_map.html',
+      'trace_viewer/model/timed_event.html',
+      'trace_viewer/model/x_marker_annotation.html',
+      'trace_viewer/trace_viewer.html',
+    ],
+    'tracing_img_files': [
+      'trace_viewer/base/images/chrome-left.png',
+      'trace_viewer/base/images/chrome-mid.png',
+      'trace_viewer/base/images/chrome-right.png',
+      'trace_viewer/base/images/ui-states.png',
+      'trace_viewer/extras/chrome/cc/images/input-event.png',
+      'trace_viewer/extras/chrome/gpu/images/checkerboard.png',
+      'trace_viewer/extras/tcmalloc/images/collapse.png',
+      'trace_viewer/extras/tcmalloc/images/expand.png',
+    ],
+    'tracing_files': [
+      '<@(tracing_css_files)',
+      '<@(tracing_js_html_files)',
+      '<@(tracing_img_files)',
+    ],
+  }
+}
diff --git a/trace-viewer/trace_viewer/base/base.html b/trace-viewer/trace_viewer/base/base.html
index 10da6c2..4cc0234 100644
--- a/trace-viewer/trace_viewer/base/base.html
+++ b/trace-viewer/trace_viewer/base/base.html
@@ -16,10 +16,10 @@
 var global = this;
 
 /** Platform, package, object property, and Event support. */
-this.tv = (function() {
-  if (window.tv) {
+this.tr = (function() {
+  if (window.tr) {
     console.warn('Base was multiply initialized. First init wins.');
-    return window.tv;
+    return window.tr;
   }
 
   /**
@@ -159,12 +159,12 @@
       }
     }
 
-    tv.doc = document;
+    tr.doc = document;
 
-    tv.isMac = /Mac/.test(navigator.platform);
-    tv.isWindows = /Win/.test(navigator.platform);
-    tv.isChromeOS = /CrOS/.test(navigator.userAgent);
-    tv.isLinux = /Linux/.test(navigator.userAgent);
+    tr.isMac = /Mac/.test(navigator.platform);
+    tr.isWindows = /Win/.test(navigator.platform);
+    tr.isChromeOS = /CrOS/.test(navigator.userAgent);
+    tr.isLinux = /Linux/.test(navigator.userAgent);
   }
 
   return {
@@ -179,5 +179,5 @@
   };
 })();
 
-tv.initialize();
+tr.initialize();
 </script>
diff --git a/trace-viewer/trace_viewer/base/base64.html b/trace-viewer/trace_viewer/base/base64.html
index 691b4b4..5b070a2 100644
--- a/trace-viewer/trace_viewer/base/base64.html
+++ b/trace-viewer/trace_viewer/base/base64.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   function Base64() {
   }
diff --git a/trace-viewer/trace_viewer/base/base64_test.html b/trace-viewer/trace_viewer/base/base64_test.html
index 61587c5..a55f651 100644
--- a/trace-viewer/trace_viewer/base/base64_test.html
+++ b/trace-viewer/trace_viewer/base/base64_test.html
@@ -8,30 +8,30 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('getDecodedLength', function() {
-    assert.isTrue(tv.b.Base64.getDecodedBufferLength('YQ==') >= 1);
-    assert.isTrue(tv.b.Base64.getDecodedBufferLength('YWJjZA==') >= 4);
-    assert.isTrue(tv.b.Base64.getDecodedBufferLength('YWJjZGVm') >= 6);
+    assert.isTrue(tr.b.Base64.getDecodedBufferLength('YQ==') >= 1);
+    assert.isTrue(tr.b.Base64.getDecodedBufferLength('YWJjZA==') >= 4);
+    assert.isTrue(tr.b.Base64.getDecodedBufferLength('YWJjZGVm') >= 6);
   });
 
   test('DecodeToTypedArray', function() {
     var buffer = new DataView(new ArrayBuffer(256));
-    tv.b.Base64.DecodeToTypedArray('YQ==', buffer);
+    tr.b.Base64.DecodeToTypedArray('YQ==', buffer);
     assert.equal(buffer.getInt8(0), 97);
 
-    tv.b.Base64.DecodeToTypedArray('YWJjZA==', buffer);
+    tr.b.Base64.DecodeToTypedArray('YWJjZA==', buffer);
     for (var i = 0; i < 4; i++)
       assert.equal(buffer.getInt8(i), 97 + i);
 
-    tv.b.Base64.DecodeToTypedArray('YWJjZGVm', buffer);
+    tr.b.Base64.DecodeToTypedArray('YWJjZGVm', buffer);
     for (var i = 0; i < 4; i++)
       assert.equal(buffer.getInt8(i), 97 + i);
   });
 
   test('DecodeLengthReturn', function() {
     var buffer = new DataView(new ArrayBuffer(256));
-    var len = tv.b.Base64.DecodeToTypedArray(btoa('hello'), buffer);
+    var len = tr.b.Base64.DecodeToTypedArray(btoa('hello'), buffer);
     assert.equal(len, 5);
   });
 });
diff --git a/trace-viewer/trace_viewer/base/bbox2.html b/trace-viewer/trace_viewer/base/bbox2.html
index e57b779..5900cbd 100644
--- a/trace-viewer/trace_viewer/base/bbox2.html
+++ b/trace-viewer/trace_viewer/base/bbox2.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/base/gl_matrix.html">
+<link rel="import" href="/base/math.html">
 <link rel="import" href="/base/rect.html">
 
 <script>
@@ -14,7 +14,7 @@
 /**
  * @fileoverview 2D bounding box computations.
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   /**
    * Tracks a 2D bounding box.
@@ -142,7 +142,7 @@
     },
 
     asRect: function() {
-      return tv.b.Rect.fromXYWH(
+      return tr.b.Rect.fromXYWH(
           this.min_[0],
           this.min_[1],
           this.max_[0] - this.min_[0],
diff --git a/trace-viewer/trace_viewer/base/bbox2_test.html b/trace-viewer/trace_viewer/base/bbox2_test.html
index 8c39b2e..428d61a 100644
--- a/trace-viewer/trace_viewer/base/bbox2_test.html
+++ b/trace-viewer/trace_viewer/base/bbox2_test.html
@@ -12,9 +12,9 @@
 
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('addVec2', function() {
-    var bbox = new tv.b.BBox2();
+    var bbox = new tr.b.BBox2();
     var x = vec2.create();
     vec2.set(x, 10, 10);
     bbox.addVec2(x);
diff --git a/trace-viewer/trace_viewer/base/category_util.html b/trace-viewer/trace_viewer/base/category_util.html
index c4ccef8..b90845a 100644
--- a/trace-viewer/trace_viewer/base/category_util.html
+++ b/trace-viewer/trace_viewer/base/category_util.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <!--
-gCopyright (c) 2013 The Chromium Authors. All rights reserved.
+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.
 -->
@@ -12,7 +12,7 @@
  * @fileoverview Helper code for working with tracing categories.
  *
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   // Cached values for getCategoryParts.
   var categoryPartsFor = {};
diff --git a/trace-viewer/trace_viewer/base/color.html b/trace-viewer/trace_viewer/base/color.html
index 6a55b67..3a4666a 100644
--- a/trace-viewer/trace_viewer/base/color.html
+++ b/trace-viewer/trace_viewer/base/color.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   function Color(opt_r, opt_g, opt_b, opt_a) {
     this.r = Math.floor(opt_r) || 0;
     this.g = Math.floor(opt_g) || 0;
diff --git a/trace-viewer/trace_viewer/base/color_test.html b/trace-viewer/trace_viewer/base/color_test.html
index 28a484c..52430b5 100644
--- a/trace-viewer/trace_viewer/base/color_test.html
+++ b/trace-viewer/trace_viewer/base/color_test.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('fromRGB', function() {
-    var c = tv.b.Color.fromString('rgb(1, 2, 3)');
+    var c = tr.b.Color.fromString('rgb(1, 2, 3)');
     assert.equal(c.r, 1);
     assert.equal(c.g, 2);
     assert.equal(c.b, 3);
@@ -18,7 +18,7 @@
   });
 
   test('FromRGBA', function() {
-    var c = tv.b.Color.fromString('rgba(1, 2, 3, 0.5)');
+    var c = tr.b.Color.fromString('rgba(1, 2, 3, 0.5)');
     assert.equal(c.r, 1);
     assert.equal(c.g, 2);
     assert.equal(c.b, 3);
@@ -26,7 +26,7 @@
   });
 
   test('fromHex', function() {
-    var c = tv.b.Color.fromString('#010203');
+    var c = tr.b.Color.fromString('#010203');
     assert.equal(c.r, 1);
     assert.equal(c.g, 2);
     assert.equal(c.b, 3);
@@ -34,28 +34,28 @@
   });
 
   test('toStringRGB', function() {
-    var c = new tv.b.Color(1, 2, 3);
+    var c = new tr.b.Color(1, 2, 3);
     assert.equal(c.toString(), 'rgb(1,2,3)');
   });
 
   test('toStringRGBA', function() {
-    var c = new tv.b.Color(1, 2, 3, 0.5);
+    var c = new tr.b.Color(1, 2, 3, 0.5);
     assert.equal(c.toString(), 'rgba(1,2,3,0.5)');
   });
 
   test('lerpRGB', function() {
-    var a = new tv.b.Color(0, 127, 191);
-    var b = new tv.b.Color(255, 255, 255);
-    var x = tv.b.Color.lerpRGB(a, b, 0.25);
+    var a = new tr.b.Color(0, 127, 191);
+    var b = new tr.b.Color(255, 255, 255);
+    var x = tr.b.Color.lerpRGB(a, b, 0.25);
     assert.equal(x.r, 63);
     assert.equal(x.g, 159);
     assert.equal(x.b, 207);
   });
 
   test('lerpRGBA', function() {
-    var a = new tv.b.Color(0, 127, 191, 0.5);
-    var b = new tv.b.Color(255, 255, 255, 1);
-    var x = tv.b.Color.lerpRGBA(a, b, 0.25);
+    var a = new tr.b.Color(0, 127, 191, 0.5);
+    var b = new tr.b.Color(255, 255, 255, 1);
+    var x = tr.b.Color.lerpRGBA(a, b, 0.25);
     assert.equal(x.r, 63);
     assert.equal(x.g, 159);
     assert.equal(x.b, 207);
@@ -63,8 +63,8 @@
   });
 
   test('blendRGBA', function() {
-    var red = new tv.b.Color(255, 0, 0, 0.5);
-    var white = new tv.b.Color(255, 255, 255, 1);
+    var red = new tr.b.Color(255, 0, 0, 0.5);
+    var white = new tr.b.Color(255, 255, 255, 1);
     var x = red.blendOver(white);
     assert.equal(x.r, 255);
     assert.equal(x.g, 127);
diff --git a/trace-viewer/trace_viewer/base/deep_utils.html b/trace-viewer/trace_viewer/base/deep_utils.html
index 328c48e..70d7795 100644
--- a/trace-viewer/trace_viewer/base/deep_utils.html
+++ b/trace-viewer/trace_viewer/base/deep_utils.html
@@ -9,7 +9,7 @@
 
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   function _iterateElementDeeplyImpl(element, cb, thisArg, includeElement) {
     if (includeElement) {
       if (cb.call(thisArg, element))
diff --git a/trace-viewer/trace_viewer/base/deep_utils_test.html b/trace-viewer/trace_viewer/base/deep_utils_test.html
index dc8eac9..e1c1516 100644
--- a/trace-viewer/trace_viewer/base/deep_utils_test.html
+++ b/trace-viewer/trace_viewer/base/deep_utils_test.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function createElement(tagName, opt_class) {
     var el = document.createElement(tagName);
     if (opt_class)
@@ -28,7 +28,7 @@
     var b_ = b.createShadowRoot();
     b_.appendChild(createElement('c', 'x'));
 
-    var m = tv.b.findDeepElementMatching(a, 'c.x');
+    var m = tr.b.findDeepElementMatching(a, 'c.x');
     assert.equal(m, b_.children[0]);
   });
 
@@ -43,9 +43,9 @@
     b_.appendChild(createElement('c', 'x'));
     b_.appendChild(createElement('c', 'x'));
 
-    var m = tv.b.findDeepElementsMatching(a, 'c.x');
+    var m = tr.b.findDeepElementsMatching(a, 'c.x');
     assert.equal(m[0], b_.children[0]);
     assert.equal(m[1], b_.children[1]);
   });
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/base/event_target.html b/trace-viewer/trace_viewer/base/event_target.html
index 281d00a..9db38bb 100644
--- a/trace-viewer/trace_viewer/base/event_target.html
+++ b/trace-viewer/trace_viewer/base/event_target.html
@@ -12,7 +12,7 @@
  * @fileoverview This contains an implementation of the EventTarget interface
  * as defined by DOM Level 2 Events.
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   /**
    * Creates a new EventTarget. This class implements the DOM level 2
diff --git a/trace-viewer/trace_viewer/base/event_target_test.html b/trace-viewer/trace_viewer/base/event_target_test.html
index b26a479..014716e 100644
--- a/trace-viewer/trace_viewer/base/event_target_test.html
+++ b/trace-viewer/trace_viewer/base/event_target_test.html
@@ -9,25 +9,25 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('eventTargetHelper', function() {
     var listenerCallCount = 0;
     function listener() { listenerCallCount++; }
 
     var div = document.createElement('div');
-    tv.b.EventTargetHelper.decorate(div);
+    tr.b.EventTargetHelper.decorate(div);
 
     assert.isFalse(div.hasEventListener('foo'));
 
     div.addEventListener('foo', listener);
     assert.isTrue(div.hasEventListener('foo'));
 
-    tv.b.dispatchSimpleEvent(div, 'foo');
+    tr.b.dispatchSimpleEvent(div, 'foo');
     assert.equal(listenerCallCount, 1);
 
     div.removeEventListener('foo', listener);
 
-    tv.b.dispatchSimpleEvent(div, 'foo');
+    tr.b.dispatchSimpleEvent(div, 'foo');
     assert.equal(listenerCallCount, 1);
 
     assert.isFalse(div.hasEventListener('foo'));
diff --git a/trace-viewer/trace_viewer/base/events.html b/trace-viewer/trace_viewer/base/events.html
index 46e02a9..6d51f4e 100644
--- a/trace-viewer/trace_viewer/base/events.html
+++ b/trace-viewer/trace_viewer/base/events.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   /**
-   * Creates a new event to be used with tv.b.EventTarget or DOM EventTarget
+   * Creates a new event to be used with tr.b.EventTarget or DOM EventTarget
    * objects.
    * @param {string} type The name of the event.
    * @param {boolean=} opt_bubbles Whether the event bubbles.
@@ -21,7 +21,7 @@
    * @extends {Event}
    */
   function Event(type, opt_bubbles, opt_preventable) {
-    var e = tv.doc.createEvent('Event');
+    var e = tr.doc.createEvent('Event');
     e.initEvent(type, !!opt_bubbles, !!opt_preventable);
     e.__proto__ = global.Event.prototype;
     return e;
diff --git a/trace-viewer/trace_viewer/base/extension_registry.html b/trace-viewer/trace_viewer/base/extension_registry.html
index d4b5e69..b6fe29e 100644
--- a/trace-viewer/trace_viewer/base/extension_registry.html
+++ b/trace-viewer/trace_viewer/base/extension_registry.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <!--
-gCopyright (c) 2013 The Chromium Authors. All rights reserved.
+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.
 -->
@@ -39,24 +39,24 @@
  * then set mandatoryBaseType field on the registry.
  *
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   function decorateExtensionRegistry(registry, registryOptions) {
     if (registry.register)
       throw new Error('Already has registry');
 
     registryOptions.freeze();
-    if (registryOptions.mode == tv.b.BASIC_REGISTRY_MODE) {
-      tv.b._decorateBasicExtensionRegistry(registry, registryOptions);
-    } else if (registryOptions.mode == tv.b.TYPE_BASED_REGISTRY_MODE) {
-      tv.b._decorateTypeBasedExtensionRegistry(registry, registryOptions);
+    if (registryOptions.mode == tr.b.BASIC_REGISTRY_MODE) {
+      tr.b._decorateBasicExtensionRegistry(registry, registryOptions);
+    } else if (registryOptions.mode == tr.b.TYPE_BASED_REGISTRY_MODE) {
+      tr.b._decorateTypeBasedExtensionRegistry(registry, registryOptions);
     } else {
       throw new Error('Unrecognized mode');
     }
 
     // Make it an event target.
     if (registry.addEventListener === undefined)
-      tv.b.EventTarget.decorate(registry);
+      tr.b.EventTarget.decorate(registry);
   }
 
   return {
diff --git a/trace-viewer/trace_viewer/base/extension_registry_base.html b/trace-viewer/trace_viewer/base/extension_registry_base.html
index 455a365..63c68ca 100644
--- a/trace-viewer/trace_viewer/base/extension_registry_base.html
+++ b/trace-viewer/trace_viewer/base/extension_registry_base.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   function RegisteredTypeInfo(constructor, metadata) {
     this.constructor = constructor;
     this.metadata = metadata;
diff --git a/trace-viewer/trace_viewer/base/extension_registry_basic.html b/trace-viewer/trace_viewer/base/extension_registry_basic.html
index fb961dd..391d7be 100644
--- a/trace-viewer/trace_viewer/base/extension_registry_basic.html
+++ b/trace-viewer/trace_viewer/base/extension_registry_basic.html
@@ -8,10 +8,10 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
-  var RegisteredTypeInfo = tv.b.RegisteredTypeInfo;
-  var ExtensionRegistryOptions = tv.b.ExtensionRegistryOptions;
+  var RegisteredTypeInfo = tr.b.RegisteredTypeInfo;
+  var ExtensionRegistryOptions = tr.b.ExtensionRegistryOptions;
 
   function decorateBasicExtensionRegistry(registry, extensionRegistryOptions) {
     var savedStateStack = [];
diff --git a/trace-viewer/trace_viewer/base/extension_registry_test.html b/trace-viewer/trace_viewer/base/extension_registry_test.html
index fe673b6..d4c8e25 100644
--- a/trace-viewer/trace_viewer/base/extension_registry_test.html
+++ b/trace-viewer/trace_viewer/base/extension_registry_test.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('tberSimpleNamedRegistration', function() {
     function DummyEvent() {
     }
@@ -22,11 +22,11 @@
       __proto__: DummyEvent.prototype
     };
 
-    var options = new tv.b.ExtensionRegistryOptions(
-        tv.b.TYPE_BASED_REGISTRY_MODE);
+    var options = new tr.b.ExtensionRegistryOptions(
+        tr.b.TYPE_BASED_REGISTRY_MODE);
     options.mandatoryBaseClass = DummyEvent;
     options.defaultConstructor = DummyEvent;
-    tv.b.decorateExtensionRegistry(
+    tr.b.decorateExtensionRegistry(
         DummyEvent, options);
 
     DummyEvent.register(DummyEventSubclass, {typeName: 'dummy-name'});
@@ -49,11 +49,11 @@
       __proto__: DummyEvent.prototype
     };
 
-    var options = new tv.b.ExtensionRegistryOptions(
-        tv.b.TYPE_BASED_REGISTRY_MODE);
+    var options = new tr.b.ExtensionRegistryOptions(
+        tr.b.TYPE_BASED_REGISTRY_MODE);
     options.mandatoryBaseClass = DummyEvent;
     options.defaultConstructor = DummyEvent;
-    tv.b.decorateExtensionRegistry(
+    tr.b.decorateExtensionRegistry(
         DummyEvent, options);
 
     DummyEvent.register(
@@ -79,11 +79,11 @@
       __proto__: DummyEvent.prototype
     };
 
-    var options = new tv.b.ExtensionRegistryOptions(
-        tv.b.TYPE_BASED_REGISTRY_MODE);
+    var options = new tr.b.ExtensionRegistryOptions(
+        tr.b.TYPE_BASED_REGISTRY_MODE);
     options.mandatoryBaseClass = DummyEvent;
     options.defaultConstructor = DummyEvent;
-    tv.b.decorateExtensionRegistry(
+    tr.b.decorateExtensionRegistry(
         DummyEvent, options);
 
     DummyEvent.register(
@@ -109,11 +109,11 @@
       __proto__: DummyEvent.prototype
     };
 
-    var options = new tv.b.ExtensionRegistryOptions(
-        tv.b.TYPE_BASED_REGISTRY_MODE);
+    var options = new tr.b.ExtensionRegistryOptions(
+        tr.b.TYPE_BASED_REGISTRY_MODE);
     options.mandatoryBaseClass = DummyEvent;
     options.defaultConstructor = DummyEvent;
-    tv.b.decorateExtensionRegistry(
+    tr.b.decorateExtensionRegistry(
         DummyEvent, options);
 
     DummyEvent.register(
diff --git a/trace-viewer/trace_viewer/base/extension_registry_type_based.html b/trace-viewer/trace_viewer/base/extension_registry_type_based.html
index 26fbc0c..8fed406 100644
--- a/trace-viewer/trace_viewer/base/extension_registry_type_based.html
+++ b/trace-viewer/trace_viewer/base/extension_registry_type_based.html
@@ -9,11 +9,11 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
-  var getCategoryParts = tv.b.getCategoryParts;
+tr.exportTo('tr.b', function() {
+  var getCategoryParts = tr.b.getCategoryParts;
 
-  var RegisteredTypeInfo = tv.b.RegisteredTypeInfo;
-  var ExtensionRegistryOptions = tv.b.ExtensionRegistryOptions;
+  var RegisteredTypeInfo = tr.b.RegisteredTypeInfo;
+  var ExtensionRegistryOptions = tr.b.ExtensionRegistryOptions;
 
 
   function decorateTypeBasedExtensionRegistry(registry,
diff --git a/trace-viewer/trace_viewer/base/guid.html b/trace-viewer/trace_viewer/base/guid.html
index ee9a259..c8184c3 100644
--- a/trace-viewer/trace_viewer/base/guid.html
+++ b/trace-viewer/trace_viewer/base/guid.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   var nextGUID = 1;
   var GUID = {
     allocate: function() {
diff --git a/trace-viewer/trace_viewer/base/interval_tree.html b/trace-viewer/trace_viewer/base/interval_tree.html
index b29b637..9b91ab6 100644
--- a/trace-viewer/trace_viewer/base/interval_tree.html
+++ b/trace-viewer/trace_viewer/base/interval_tree.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   function max(a, b) {
     if (a === undefined)
       return b;
diff --git a/trace-viewer/trace_viewer/base/interval_tree_test.html b/trace-viewer/trace_viewer/base/interval_tree_test.html
index a33e16a..0a8f28a 100644
--- a/trace-viewer/trace_viewer/base/interval_tree_test.html
+++ b/trace-viewer/trace_viewer/base/interval_tree_test.html
@@ -8,15 +8,15 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function SimpleIntervalTree() {
-    tv.b.IntervalTree.call(this,
+    tr.b.IntervalTree.call(this,
         function(s) { return s.start; },
         function(s) { return s.end; });
     return this;
   }
   SimpleIntervalTree.prototype = {
-    __proto__: tv.b.IntervalTree.prototype
+    __proto__: tr.b.IntervalTree.prototype
   };
 
   function buildSimpleTree() {
@@ -72,7 +72,7 @@
   });
 
   test('findIntersection_emptyTree', function() {
-    var tree = new tv.b.IntervalTree();
+    var tree = new tr.b.IntervalTree();
     tree.updateHighValues();
 
     var intersection = tree.findIntersection(2, 4);
@@ -80,7 +80,7 @@
   });
 
   test('findIntersection_emptyInterval', function() {
-    var tree = new tv.b.IntervalTree();
+    var tree = new tr.b.IntervalTree();
     tree.updateHighValues();
 
     assert.throws(function() {
@@ -95,7 +95,7 @@
   });
 
   test('insert', function() {
-    var tree = new tv.b.IntervalTree(
+    var tree = new tr.b.IntervalTree(
         function(s) { return s.start; },
         function(s) { return s.end; });
 
@@ -117,7 +117,7 @@
   });
 
   test('insert_withoutEnd', function() {
-    var tree = new tv.b.IntervalTree(
+    var tree = new tr.b.IntervalTree(
         function(s) { return s.start; },
         function(s) { return s.end; });
 
@@ -139,7 +139,7 @@
   });
 
   test('insert_balancesTree', function() {
-    var tree = new tv.b.IntervalTree(
+    var tree = new tr.b.IntervalTree(
         function(s) { return s.start; },
         function(s) { return s.end; });
 
@@ -184,7 +184,7 @@
   });
 
   test('insert_withDuplicateIntervals', function() {
-    var tree = new tv.b.IntervalTree(
+    var tree = new tr.b.IntervalTree(
         function(s) { return s.start; },
         function(s) { return s.end; });
 
diff --git a/trace-viewer/trace_viewer/base/iteration_helpers.html b/trace-viewer/trace_viewer/base/iteration_helpers.html
index b6aa778..31b2876 100644
--- a/trace-viewer/trace_viewer/base/iteration_helpers.html
+++ b/trace-viewer/trace_viewer/base/iteration_helpers.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   function asArray(arrayish) {
     var values = [];
     for (var i = 0; i < arrayish.length; i++)
@@ -36,9 +36,9 @@
    * Compares two values when one or both might be undefined. Undefined
    * values are sorted after defined.
    */
-  function comparePossiblyUndefinedValues(x, y, cmp) {
+  function comparePossiblyUndefinedValues(x, y, cmp, opt_this) {
     if (x !== undefined && y !== undefined)
-      return cmp(x, y);
+      return cmp.call(opt_this, x, y);
     if (x !== undefined)
       return -1;
     if (y !== undefined)
@@ -88,6 +88,26 @@
     return n;
   }
 
+  /**
+   * Returns a new dictionary with items grouped by the return value of the
+   * specified function being called on each item.
+   * @param {!Array.<Object>} ary The array being iterated through
+   * @param {!Function} fn The mapping function between the array value and the
+   * map key.
+   */
+  function group(ary, fn) {
+    return ary.reduce(function(accumulator, curr) {
+      var key = fn(curr);
+
+      if (key in accumulator)
+        accumulator[key].push(curr);
+      else
+        accumulator[key] = [curr];
+
+      return accumulator;
+    }, {});
+  }
+
   function iterItems(dict, fn, opt_this) {
     opt_this = opt_this || this;
     var keys = Object.keys(dict);
@@ -167,6 +187,7 @@
     dictionaryLength: dictionaryLength,
     dictionaryKeys: dictionaryKeys,
     dictionaryValues: dictionaryValues,
+    group: group,
     iterItems: iterItems,
     mapItems: mapItems,
     iterObjectFieldsRecursively: iterObjectFieldsRecursively,
diff --git a/trace-viewer/trace_viewer/base/iteration_helpers_test.html b/trace-viewer/trace_viewer/base/iteration_helpers_test.html
index eb8c227..be30985 100644
--- a/trace-viewer/trace_viewer/base/iteration_helpers_test.html
+++ b/trace-viewer/trace_viewer/base/iteration_helpers_test.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var comparePossiblyUndefinedValues = tv.b.comparePossiblyUndefinedValues;
-  var compareArrays = tv.b.compareArrays;
+tr.b.unittest.testSuite(function() {
+  var comparePossiblyUndefinedValues = tr.b.comparePossiblyUndefinedValues;
+  var compareArrays = tr.b.compareArrays;
 
   test('comparePossiblyUndefinedValues', function() {
     function cmp(x, y) {
@@ -50,10 +50,28 @@
     assert.equal(compareArrays([1], [1], cmp), 0);
   });
 
+  test('group', function() {
+    // Empty array
+    var srcArray = [];
+    var fn = function(curr) { return (curr % 2); }
+    var dstDict = {};
+
+    assert.deepEqual(tr.b.group(srcArray, fn), dstDict);
+
+    // Non-empty array
+    var srcArray = [0, 1, 2, 3, 4, 5, 6];
+    var dstDict = {
+      0: [0, 2, 4, 6],
+      1: [1, 3, 5]
+    };
+
+    assert.deepEqual(tr.b.group(srcArray, fn), dstDict);
+  });
+
   test('mapItems', function() {
     // Empty dictionary.
     var srcDict = {};
-    var dstDict = tv.b.mapItems(srcDict, function(key, value) {
+    var dstDict = tr.b.mapItems(srcDict, function(key, value) {
       return value;
     });
     assert.lengthOf(Object.keys(srcDict), 0);
@@ -62,7 +80,7 @@
 
     // Non-empty dictionary.
     var srcDict = {a: 0, b: 30};
-    var dstDict = tv.b.mapItems(srcDict, function(key, value) {
+    var dstDict = tr.b.mapItems(srcDict, function(key, value) {
       return 9 * value / 5 + 32;
     });
     assert.lengthOf(Object.keys(srcDict), 2);
@@ -75,7 +93,7 @@
 
     // Optional 'this' argument.
     var srcDict = {c: '?', d: '!', e: '.'};
-    var dstDict = tv.b.mapItems(srcDict, function(key, value) {
+    var dstDict = tr.b.mapItems(srcDict, function(key, value) {
       return key + this.delimiter + value;
     }, {delimiter: '='});
     assert.lengthOf(Object.keys(srcDict), 3);
@@ -90,7 +108,7 @@
 
     // Inherited properties should not be mapped.
     var srcDict = {__proto__: {a: 10}};
-    var dstDict = tv.b.mapItems(srcDict, function(key, value) {
+    var dstDict = tr.b.mapItems(srcDict, function(key, value) {
       return value;
     });
     assert.lengthOf(Object.keys(srcDict), 0);
@@ -99,18 +117,18 @@
 
   test('identity', function() {
     // Undefined value.
-    assert.isUndefined(tv.b.identity(undefined));
+    assert.isUndefined(tr.b.identity(undefined));
 
     // Primitive value.
-    assert.equal(tv.b.identity(-273.15), -273.15);
+    assert.equal(tr.b.identity(-273.15), -273.15);
 
     // List.
     var list = ['list', 'with', 1, undefined, 'value'];
-    assert.strictEqual(tv.b.identity(list), list);
+    assert.strictEqual(tr.b.identity(list), list);
 
     // Object.
     var object = {'hasItems': true};
-    assert.strictEqual(tv.b.identity(object), object);
+    assert.strictEqual(tr.b.identity(object), object);
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/base/key_event_manager.html b/trace-viewer/trace_viewer/base/key_event_manager.html
index 9641050..77eb7e6 100644
--- a/trace-viewer/trace_viewer/base/key_event_manager.html
+++ b/trace-viewer/trace_viewer/base/key_event_manager.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   /**
    * KeyEventManager avoids leaks when listening for keys.
@@ -40,7 +40,7 @@
   }
   KeyEventManager.instance = undefined;
 
-  document.head.addEventListener('tv-unittest-will-run', function() {
+  document.head.addEventListener('tr-unittest-will-run', function() {
     if (KeyEventManager.instance) {
       KeyEventManager.instance.destroy();
       KeyEventManager.instance = undefined;
@@ -51,7 +51,7 @@
   KeyEventManager.prototype = {
     addListener: function(type, handler, thisArg) {
       if (!thisArg.keyEventManagerGuid_) {
-        thisArg.keyEventManagerGuid_ = tv.b.GUID.allocate();
+        thisArg.keyEventManagerGuid_ = tr.b.GUID.allocate();
         thisArg.keyEventManagerRefCount_ = 0;
       }
       thisArg.classList.add('key-event-manager-target');
diff --git a/trace-viewer/trace_viewer/base/key_event_manager_test.html b/trace-viewer/trace_viewer/base/key_event_manager_test.html
index 0ba68c7..06bf07f 100644
--- a/trace-viewer/trace_viewer/base/key_event_manager_test.html
+++ b/trace-viewer/trace_viewer/base/key_event_manager_test.html
@@ -8,8 +8,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var KeyEventManager = tv.b.KeyEventManager;
+tr.b.unittest.testSuite(function() {
+  var KeyEventManager = tr.b.KeyEventManager;
 
   function withElementAttachedToChild(element, callback) {
     document.body.appendChild(element);
diff --git a/trace-viewer/trace_viewer/base/gl_matrix.html b/trace-viewer/trace_viewer/base/math.html
similarity index 69%
rename from trace-viewer/trace_viewer/base/gl_matrix.html
rename to trace-viewer/trace_viewer/base/math.html
index 88034b9..1953e95 100644
--- a/trace-viewer/trace_viewer/base/gl_matrix.html
+++ b/trace-viewer/trace_viewer/base/math.html
@@ -6,10 +6,24 @@
 -->
 <link rel="import" href="/base/base.html">
 <script src="/gl-matrix-min.js"></script>
+
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
+  function clamp(x, lo, hi) {
+    return Math.min(Math.max(x, lo), hi);
+  }
+
+  function lerp(percentage, lo, hi) {
+    var range = hi - lo;
+    return lo + percentage * range;
+  }
+
+  function deg2rad(deg) {
+    return (Math.PI * deg) / 180.0;
+  }
+
   var tmp_vec2 = vec2.create();
   var tmp_vec2b = vec2.create();
   var tmp_vec4 = vec4.create();
@@ -38,7 +52,20 @@
     vec2.scale(tmp_vec2, u1, scale1);
     vec2.scale(tmp_vec2b, u2, scale2);
     vec2.add(out, tmp_vec2, tmp_vec2b);
-  }
+  };
+
+  vec2.interpolatePiecewiseFunction = function(points, x) {
+    if (x < points[0][0])
+      return points[0][1];
+    for (var i = 1; i < points.length; ++i) {
+      if (x < points[i][0]) {
+        var percent = (x - points[i - 1][0]) /
+                      (points[i][0] - points[i - 1][0]);
+        return lerp(percent, points[i - 1][1], points[i][1]);
+      }
+    }
+    return points[points.length - 1][1];
+  };
 
   vec3.createXYZ = function(x, y, z) {
     var v = vec3.create();
@@ -73,6 +100,11 @@
     vec2.copy(out, tmp_vec4);
   }
 
-  return {};
+  return {
+    clamp: clamp,
+    lerp: lerp,
+    deg2rad: deg2rad
+  };
+
 });
 </script>
diff --git a/trace-viewer/trace_viewer/base/math_test.html b/trace-viewer/trace_viewer/base/math_test.html
new file mode 100644
index 0000000..f2ab2bd
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/math_test.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 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="import" href="/base/math.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('clamping', function() {
+    assert.equal(tr.b.clamp(2, 1, 3), 2);
+    assert.equal(tr.b.clamp(1, 1, 3), 1);
+    assert.equal(tr.b.clamp(0, 1, 3), 1);
+    assert.equal(tr.b.clamp(3, 1, 3), 3);
+    assert.equal(tr.b.clamp(4, 1, 3), 3);
+  });
+
+  test('interpolatePiecewiseFunction', function() {
+    var points = [[0, 0], [0.1, 0.5], [1, 1]];
+    assert.equal(0, vec2.interpolatePiecewiseFunction(points, -1));
+    assert.equal(0, vec2.interpolatePiecewiseFunction(points, 0));
+    assert.equal(0.25, vec2.interpolatePiecewiseFunction(points, 0.05));
+    assert.equal(0.5, vec2.interpolatePiecewiseFunction(points, 0.1));
+    assert.equal(0.75, vec2.interpolatePiecewiseFunction(points, 0.55));
+    assert.equal(1, vec2.interpolatePiecewiseFunction(points, 1));
+    assert.equal(1, vec2.interpolatePiecewiseFunction(points, 2));
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/polymer_utils.html b/trace-viewer/trace_viewer/base/polymer_utils.html
index 9c98b53..b449a3d 100644
--- a/trace-viewer/trace_viewer/base/polymer_utils.html
+++ b/trace-viewer/trace_viewer/base/polymer_utils.html
@@ -12,7 +12,7 @@
 /**
  * @fileoverview Helper code for working with Polymer.
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   Object.observe(Polymer.elements, clearPolymerElementCaches);
 
diff --git a/trace-viewer/trace_viewer/base/properties.html b/trace-viewer/trace_viewer/base/properties.html
index 51a54e7..45c2b7e 100644
--- a/trace-viewer/trace_viewer/base/properties.html
+++ b/trace-viewer/trace_viewer/base/properties.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   /**
    * Fires a property change event on the target.
    * @param {EventTarget} target The target to dispatch the event on.
@@ -18,7 +18,7 @@
    */
   function dispatchPropertyChange(target, propertyName, newValue, oldValue,
                                   opt_bubbles, opt_cancelable) {
-    var e = new tv.b.Event(propertyName + 'Change',
+    var e = new tr.b.Event(propertyName + 'Change',
                            opt_bubbles, opt_cancelable);
     e.propertyName = propertyName;
     e.newValue = newValue;
@@ -39,7 +39,7 @@
     var oldValue = obj[propertyName];
     obj[privateName] = newValue;
     if (oldValue !== newValue)
-      tv.b.dispatchPropertyChange(obj, propertyName,
+      tr.b.dispatchPropertyChange(obj, propertyName,
           newValue, oldValue, true, false);
   }
 
@@ -58,7 +58,7 @@
    * @return {string} an obfuscated name
    */
   function getPrivateName(name) {
-    return name + '_tv_';
+    return name + '_tr_';
   }
 
   /**
@@ -89,7 +89,7 @@
    * Helper function for defineProperty that returns the getter to use for the
    * property.
    * @param {string} name The name of the property.
-   * @param {tv.b.PropertyKind} kind The kind of the property.
+   * @param {tr.b.PropertyKind} kind The kind of the property.
    * @return {function():*} The getter for the property.
    */
   function getGetter(name, kind) {
@@ -117,7 +117,7 @@
    * kind.
    * @param {string} name The name of the property we are defining the setter
    *     for.
-   * @param {tv.b.PropertyKind} kind The kind of property we are getting the
+   * @param {tr.b.PropertyKind} kind The kind of property we are getting the
    *     setter for.
    * @param {function(*):void=} opt_setHook A function to run after the property
    *     is set, but before the propertyChange event is fired.
@@ -180,7 +180,7 @@
    * property change event with the type {@code name + 'Change'} is fired.
    * @param {!Object} obj The object to define the property for.
    * @param {string} name The name of the property.
-   * @param {tv.b.PropertyKind=} opt_kind What kind of underlying storage to
+   * @param {tr.b.PropertyKind=} opt_kind What kind of underlying storage to
    * use.
    * @param {function(*):void=} opt_setHook A function to run after the
    *     property is set, but before the propertyChange event is fired.
@@ -190,7 +190,7 @@
    */
   function defineProperty(obj, name, opt_kind, opt_setHook,
                           opt_bubbles, opt_cancelable) {
-    console.error("Don't use tv.b.defineProperty");
+    console.error("Don't use tr.b.defineProperty");
     if (typeof obj == 'function')
       obj = obj.prototype;
 
diff --git a/trace-viewer/trace_viewer/base/properties_test.html b/trace-viewer/trace_viewer/base/properties_test.html
index 8d446b8..693bd14 100644
--- a/trace-viewer/trace_viewer/base/properties_test.html
+++ b/trace-viewer/trace_viewer/base/properties_test.html
@@ -8,11 +8,11 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('defineProperties', function() {
     var stateChanges = [];
 
-    var ASpan = tv.b.ui.define('span');
+    var ASpan = tr.b.ui.define('span');
     ASpan.prototype = {
       __proto__: HTMLSpanElement.prototype,
 
@@ -31,7 +31,7 @@
       },
 
       set prop(newValue) {
-        tv.b.setPropertyAndDispatchChange(this, 'prop', newValue);
+        tr.b.setPropertyAndDispatchChange(this, 'prop', newValue);
       }
     };
 
diff --git a/trace-viewer/trace_viewer/base/quad.html b/trace-viewer/trace_viewer/base/quad.html
index 81d03de..9d61e1f 100644
--- a/trace-viewer/trace_viewer/base/quad.html
+++ b/trace-viewer/trace_viewer/base/quad.html
@@ -5,11 +5,11 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/base/gl_matrix.html">
+<link rel="import" href="/base/math.html">
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   var tmpVec2s = [];
   for (var i = 0; i < 8; i++)
     tmpVec2s[i] = vec2.create();
@@ -97,7 +97,7 @@
       var x1 = Math.max(this.p1[0], this.p2[0], this.p3[0], this.p4[0]);
       var y1 = Math.max(this.p1[1], this.p2[1], this.p3[1], this.p4[1]);
 
-      return new tv.b.Rect.fromXYWH(x0, y0, x1 - x0, y1 - y0);
+      return new tr.b.Rect.fromXYWH(x0, y0, x1 - x0, y1 - y0);
     },
 
     clone: function() {
diff --git a/trace-viewer/trace_viewer/base/quad_test.html b/trace-viewer/trace_viewer/base/quad_test.html
index 01d705b..7571a23 100644
--- a/trace-viewer/trace_viewer/base/quad_test.html
+++ b/trace-viewer/trace_viewer/base/quad_test.html
@@ -19,12 +19,12 @@
     return;
   var message = opt_message || 'Expected "' + a.toString() +
       '", got "' + b.toString() + '"';
-  throw new tv.b.unittest.TestError(message);
+  throw new tr.b.unittest.TestError(message);
 }
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('pointInTri', function() {
-    var res = tv.b.pointInTriangle2(
+    var res = tr.b.pointInTriangle2(
         [0.25, 0.25],
         [0, 0],
         [1, 0],
@@ -33,7 +33,7 @@
   });
 
   test('pointNotInTri', function() {
-    var res = tv.b.pointInTriangle2(
+    var res = tr.b.pointInTriangle2(
         [0.75, 0.75],
         [0, 0],
         [1, 0],
@@ -42,7 +42,7 @@
   });
 
   test('pointInside', function() {
-    var q = tv.b.Quad.from4Vecs([0, 0],
+    var q = tr.b.Quad.from4Vecs([0, 0],
                                 [1, 0],
                                 [1, 1],
                                 [0, 1]);
@@ -51,7 +51,7 @@
   });
 
   test('pointNotInQuad', function() {
-    var q = tv.b.Quad.from4Vecs([0, 0],
+    var q = tr.b.Quad.from4Vecs([0, 0],
                                 [1, 0],
                                 [1, 1],
                                 [0, 1]);
@@ -60,71 +60,71 @@
   });
 
   test('isRectangle', function() {
-    assert.isTrue(tv.b.Quad.fromXYWH(0, 0, 10, 10).isRectangle());
-    assert.isTrue(tv.b.Quad.fromXYWH(-10, -10, 5, 5).isRectangle());
-    assert.isTrue(tv.b.Quad.fromXYWH(-10, -10, 20, 20).isRectangle());
-    assert.isTrue(tv.b.Quad.fromXYWH(-10, 10, 5, 5).isRectangle());
+    assert.isTrue(tr.b.Quad.fromXYWH(0, 0, 10, 10).isRectangle());
+    assert.isTrue(tr.b.Quad.fromXYWH(-10, -10, 5, 5).isRectangle());
+    assert.isTrue(tr.b.Quad.fromXYWH(-10, -10, 20, 20).isRectangle());
+    assert.isTrue(tr.b.Quad.fromXYWH(-10, 10, 5, 5).isRectangle());
 
-    assert.isFalse(tv.b.Quad.fromXYWH(0, 0, -10, -10).isRectangle());
+    assert.isFalse(tr.b.Quad.fromXYWH(0, 0, -10, -10).isRectangle());
     assert.isFalse(
-        tv.b.Quad.from8Array([0, 1, 2, 3, 4, 5, 6, 7]).isRectangle());
+        tr.b.Quad.from8Array([0, 1, 2, 3, 4, 5, 6, 7]).isRectangle());
     assert.isFalse(
-        tv.b.Quad.from8Array([0, 0, 0, 5, 5, 5, 0, 0]).isRectangle());
+        tr.b.Quad.from8Array([0, 0, 0, 5, 5, 5, 0, 0]).isRectangle());
   });
 
   test('projectUnitRect', function() {
-    var container = tv.b.Quad.fromXYWH(0, 0, 10, 10);
-    var srcRect = tv.b.Rect.fromXYWH(0.1, 0.8, 0.8, 0.1);
+    var container = tr.b.Quad.fromXYWH(0, 0, 10, 10);
+    var srcRect = tr.b.Rect.fromXYWH(0.1, 0.8, 0.8, 0.1);
     var expectedRect = srcRect.scale(10);
 
-    var q = new tv.b.Quad();
+    var q = new tr.b.Quad();
     container.projectUnitRectFast(q, srcRect);
 
-    assertQuadEquals(tv.b.Quad.fromRect(expectedRect), q);
+    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
   });
 
   test('projectUnitRectOntoUnitQuad', function() {
-    var container = tv.b.Quad.fromXYWH(0, 0, 1, 1);
-    var srcRect = tv.b.Rect.fromXYWH(0.0, 0, 1, 1);
+    var container = tr.b.Quad.fromXYWH(0, 0, 1, 1);
+    var srcRect = tr.b.Rect.fromXYWH(0.0, 0, 1, 1);
     var expectedRect = srcRect;
 
-    var q = new tv.b.Quad();
+    var q = new tr.b.Quad();
     container.projectUnitRectFast(q, srcRect);
 
-    assertQuadEquals(tv.b.Quad.fromRect(expectedRect), q);
+    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
   });
 
   test('projectUnitRectOntoSizeTwoQuad', function() {
-    var container = tv.b.Quad.fromXYWH(0, 0, 2, 2);
-    var srcRect = tv.b.Rect.fromXYWH(0.0, 0, 1, 1);
+    var container = tr.b.Quad.fromXYWH(0, 0, 2, 2);
+    var srcRect = tr.b.Rect.fromXYWH(0.0, 0, 1, 1);
     var expectedRect = srcRect.scale(2);
 
-    var q = new tv.b.Quad();
+    var q = new tr.b.Quad();
     container.projectUnitRectFast(q, srcRect);
 
-    assertQuadEquals(tv.b.Quad.fromRect(expectedRect), q);
+    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
   });
 
   test('projectUnitRectOntoTranslatedQuad', function() {
-    var container = tv.b.Quad.fromXYWH(1, 1, 1, 1);
-    var srcRect = tv.b.Rect.fromXYWH(0.0, 0, 1, 1);
+    var container = tr.b.Quad.fromXYWH(1, 1, 1, 1);
+    var srcRect = tr.b.Rect.fromXYWH(0.0, 0, 1, 1);
     var expectedRect = srcRect.translate([1, 1]);
 
-    var q = new tv.b.Quad();
+    var q = new tr.b.Quad();
     container.projectUnitRectFast(q, srcRect);
 
-    assertQuadEquals(tv.b.Quad.fromRect(expectedRect), q);
+    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
   });
 
   test('projectShrunkUnitRectOntoUnitQuad', function() {
-    var container = tv.b.Quad.fromXYWH(0, 0, 1, 1);
-    var srcRect = tv.b.Rect.fromXYWH(0.1, 0.1, 0.8, 0.8);
+    var container = tr.b.Quad.fromXYWH(0, 0, 1, 1);
+    var srcRect = tr.b.Rect.fromXYWH(0.1, 0.1, 0.8, 0.8);
     var expectedRect = srcRect;
 
-    var q = new tv.b.Quad();
+    var q = new tr.b.Quad();
     container.projectUnitRectFast(q, srcRect);
 
-    assertQuadEquals(tv.b.Quad.fromRect(expectedRect), q);
+    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/base/raf.html b/trace-viewer/trace_viewer/base/raf.html
index e642de2..c224743 100644
--- a/trace-viewer/trace_viewer/base/raf.html
+++ b/trace-viewer/trace_viewer/base/raf.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   // Setting this to true will cause stack traces to get dumped into the
   // tasks. When an exception happens the original stack will be printed.
   //
@@ -50,7 +50,7 @@
     try {
       task.callback.call(task.context, frameBeginTime);
     } catch (e) {
-      tv.b.onAnimationFrameError(e, task.stack);
+      tr.b.onAnimationFrameError(e, task.stack);
     }
   }
 
@@ -93,7 +93,7 @@
     if (!recordRAFStacks)
       return '';
 
-    var stackLines = tv.b.stackTrace();
+    var stackLines = tr.b.stackTrace();
     // Strip off getStack_.
     stackLines.shift();
     return stackLines.join('\n');
diff --git a/trace-viewer/trace_viewer/base/raf_test.html b/trace-viewer/trace_viewer/base/raf_test.html
index 341b832..5d10c06 100644
--- a/trace-viewer/trace_viewer/base/raf_test.html
+++ b/trace-viewer/trace_viewer/base/raf_test.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var fakeNow = undefined;
   function withFakeWindowPerformanceNow(func) {
     var oldNow = window.performance.now;
@@ -22,41 +22,41 @@
 
   test('runIdleTaskWhileIdle', function() {
     withFakeWindowPerformanceNow(function() {
-      tv.b.forcePendingRAFTasksToRun(100000);  // Clear current RAF task queue.
+      tr.b.forcePendingRAFTasksToRun(100000);  // Clear current RAF task queue.
 
       var rafRan = false;
-      tv.b.requestAnimationFrame(function() {
+      tr.b.requestAnimationFrame(function() {
         rafRan = true;
       });
       var idleRan = false;
-      tv.b.requestIdleCallback(function() {
+      tr.b.requestIdleCallback(function() {
         idleRan = true;
       });
       fakeNow = 0;
-      tv.b.forcePendingRAFTasksToRun(fakeNow);
+      tr.b.forcePendingRAFTasksToRun(fakeNow);
       assert.isFalse(idleRan);
       assert.isTrue(rafRan);
-      tv.b.forcePendingRAFTasksToRun(fakeNow);
+      tr.b.forcePendingRAFTasksToRun(fakeNow);
       assert.isTrue(idleRan);
     });
   });
 
   test('twoShortIdleCallbacks', function() {
     withFakeWindowPerformanceNow(function() {
-      tv.b.forcePendingRAFTasksToRun(100000);  // Clear current RAF task queue.
+      tr.b.forcePendingRAFTasksToRun(100000);  // Clear current RAF task queue.
 
       var idle1Ran = false;
       var idle2Ran = false;
-      tv.b.requestIdleCallback(function() {
+      tr.b.requestIdleCallback(function() {
         fakeNow += 1;
         idle1Ran = true;
       });
-      tv.b.requestIdleCallback(function() {
+      tr.b.requestIdleCallback(function() {
         fakeNow += 1;
         idle2Ran = true;
       });
       fakeNow = 0;
-      tv.b.forcePendingRAFTasksToRun(fakeNow);
+      tr.b.forcePendingRAFTasksToRun(fakeNow);
       assert.isTrue(idle1Ran);
       assert.isTrue(idle2Ran);
     });
@@ -65,20 +65,20 @@
 
   test('oneLongOneShortIdleCallback', function() {
     withFakeWindowPerformanceNow(function() {
-      tv.b.forcePendingRAFTasksToRun(100000);  // Clear current RAF task queue.
+      tr.b.forcePendingRAFTasksToRun(100000);  // Clear current RAF task queue.
 
       var idle1Ran = false;
       var idle2Ran = false;
-      tv.b.requestIdleCallback(function() {
+      tr.b.requestIdleCallback(function() {
         fakeNow += 100;
         idle1Ran = true;
       });
-      tv.b.requestIdleCallback(function() {
+      tr.b.requestIdleCallback(function() {
         fakeNow += 1;
         idle2Ran = true;
       });
       fakeNow = 0;
-      tv.b.forcePendingRAFTasksToRun(fakeNow);
+      tr.b.forcePendingRAFTasksToRun(fakeNow);
       assert.isTrue(idle1Ran);
       assert.isFalse(idle2Ran);
 
@@ -86,7 +86,7 @@
       idle1Ran = false;
 
       // Now run. idle2 should now run.
-      tv.b.forcePendingRAFTasksToRun(fakeNow);
+      tr.b.forcePendingRAFTasksToRun(fakeNow);
       assert.isFalse(idle1Ran);
       assert.isTrue(idle2Ran);
     });
@@ -94,20 +94,20 @@
 
   test('buggyPerformanceNowDoesNotBlockIdleTasks', function() {
     withFakeWindowPerformanceNow(function() {
-      tv.b.forcePendingRAFTasksToRun();  // Clear current RAF task queue.
+      tr.b.forcePendingRAFTasksToRun();  // Clear current RAF task queue.
 
       var idle1Ran = false;
       var idle2Ran = false;
-      tv.b.requestIdleCallback(function() {
+      tr.b.requestIdleCallback(function() {
         fakeNow += 100;
         idle1Ran = true;
       });
-      tv.b.requestIdleCallback(function() {
+      tr.b.requestIdleCallback(function() {
         fakeNow += 1;
         idle2Ran = true;
       });
       fakeNow = 10000;
-      tv.b.forcePendingRAFTasksToRun(0);
+      tr.b.forcePendingRAFTasksToRun(0);
       assert.isTrue(idle1Ran);
       assert.isFalse(idle2Ran);
 
@@ -115,7 +115,7 @@
       idle1Ran = false;
 
       // Now run. idle2 should now run.
-      tv.b.forcePendingRAFTasksToRun(0);
+      tr.b.forcePendingRAFTasksToRun(0);
       assert.isFalse(idle1Ran);
       assert.isTrue(idle2Ran);
     });
diff --git a/trace-viewer/trace_viewer/base/range.html b/trace-viewer/trace_viewer/base/range.html
index 7115940..7ee1285 100644
--- a/trace-viewer/trace_viewer/base/range.html
+++ b/trace-viewer/trace_viewer/base/range.html
@@ -11,7 +11,7 @@
 /**
  * @fileoverview Quick range computations.
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   function Range() {
     this.isEmpty_ = true;
@@ -118,6 +118,13 @@
     }
   };
 
+  Range.fromExplicitRange = function(min, max) {
+    var range = new Range();
+    range.min = min;
+    range.max = max;
+    return range;
+  };
+
   Range.compareByMinTimes = function(a, b) {
     if (!a.isEmpty && !b.isEmpty)
       return a.min_ - b.min_;
@@ -134,6 +141,5 @@
   return {
     Range: Range
   };
-
 });
 </script>
diff --git a/trace-viewer/trace_viewer/base/range_test.html b/trace-viewer/trace_viewer/base/range_test.html
index e69fe0c..d3690e1 100644
--- a/trace-viewer/trace_viewer/base/range_test.html
+++ b/trace-viewer/trace_viewer/base/range_test.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('addValue', function() {
-    var range = new tv.b.Range();
+    var range = new tr.b.Range();
     assert.isTrue(range.isEmpty);
     range.addValue(1);
     assert.isFalse(range.isEmpty);
@@ -24,20 +24,20 @@
   });
 
   test('addNonEmptyRange', function() {
-    var r1 = new tv.b.Range();
+    var r1 = new tr.b.Range();
     r1.addValue(1);
     r1.addValue(2);
 
-    var r = new tv.b.Range();
+    var r = new tr.b.Range();
     r.addRange(r1);
     assert.equal(1, r.min);
     assert.equal(2, r.max);
   });
 
   test('addEmptyRange', function() {
-    var r1 = new tv.b.Range();
+    var r1 = new tr.b.Range();
 
-    var r = new tv.b.Range();
+    var r = new tr.b.Range();
     r.addRange(r1);
     assert.isTrue(r.isEmpty);
     assert.isUndefined(r.min);
@@ -45,11 +45,11 @@
   });
 
   test('addRangeToRange', function() {
-    var r1 = new tv.b.Range();
+    var r1 = new tr.b.Range();
     r1.addValue(1);
     r1.addValue(2);
 
-    var r = new tv.b.Range();
+    var r = new tr.b.Range();
     r.addValue(3);
     r.addRange(r1);
 
diff --git a/trace-viewer/trace_viewer/base/range_utils.html b/trace-viewer/trace_viewer/base/range_utils.html
new file mode 100644
index 0000000..a261b41
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/range_utils.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 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="import" href="/base/base.html">
+<link rel="import" href="/base/iteration_helpers.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides event merging functionality for grouping/analysis.
+ */
+tr.exportTo('tr.e.audits', function() {
+  function mergeRanges(inRanges, mergeThreshold, mergeFunction) {
+    return mergeExplicitRanges(inRanges,
+                               mergeThreshold,
+                               mergeFunction,
+                               function(r) { return r.min; },
+                               function(r) { return r.max; });
+  }
+
+  function mergeExplicitRanges(inRanges, mergeThreshold, mergeFunction,
+                       opt_startFunction, opt_endFunction) {
+    var startFunction = opt_startFunction;
+    var endFunction = opt_endFunction;
+    if (!startFunction)
+      startFunction = function(event) { return event.start; };
+    if (!endFunction)
+      endFunction = function(event) { return event.end; };
+
+    var remainingEvents = inRanges.slice();
+    remainingEvents.sort(function(x, y) {
+      return startFunction(x) - startFunction(y);
+    });
+
+    if (remainingEvents.length <= 1) {
+      var merged = [];
+      if (remainingEvents.length == 1) {
+        merged.push(mergeFunction(remainingEvents));
+      }
+      return merged;
+    }
+
+    var mergedEvents = [];
+
+    var currentMergeBuffer = [];
+    var rightEdge;
+    function beginMerging() {
+      currentMergeBuffer.push(remainingEvents[0]);
+      remainingEvents.splice(0, 1);
+      rightEdge = endFunction(currentMergeBuffer[0]);
+    }
+
+    function flushCurrentMergeBuffer() {
+      if (currentMergeBuffer.length == 0)
+        return;
+
+      mergedEvents.push(mergeFunction(currentMergeBuffer));
+      currentMergeBuffer = [];
+
+      // Refill merge buffer if needed.
+      if (remainingEvents.length != 0)
+        beginMerging();
+    }
+
+    beginMerging();
+
+    while (remainingEvents.length) {
+      var currentEvent = remainingEvents[0];
+
+      var distanceFromRightEdge = startFunction(currentEvent) - rightEdge;
+      if (distanceFromRightEdge < mergeThreshold) {
+        rightEdge = Math.max(rightEdge, endFunction(currentEvent));
+        remainingEvents.splice(0, 1);
+        currentMergeBuffer.push(currentEvent);
+        continue;
+      }
+
+      // Too big a gap.
+      flushCurrentMergeBuffer();
+    }
+    flushCurrentMergeBuffer();
+
+    return mergedEvents;
+  }
+
+  // 'opt_totalRange' allows capturing an empty range before the first of
+  // 'inRanges' and after the last of 'inRanges'.
+  function findEmptyRangesBetweenExplicitRanges(
+      inRanges, opt_totalRange, opt_startFunction, opt_endFunction) {
+    var startFunction = opt_startFunction;
+    if (!startFunction)
+      startFunction = function(range) { return range.start; };
+    var endFunction = opt_endFunction;
+    if (!endFunction)
+      endFunction = function(range) { return range.end; };
+
+    var emptyRanges = [];
+    if (!inRanges.length) {
+      if (opt_totalRange) {
+        emptyRanges.push(tr.b.Range.fromExplicitRange(
+            startFunction(opt_totalRange), endFunction(opt_totalRange)));
+      }
+      return emptyRanges;
+    }
+
+    inRanges = inRanges.slice();
+    inRanges.sort(function(x, y) {
+      return startFunction(x) - startFunction(y);
+    });
+    if (opt_totalRange &&
+        (startFunction(opt_totalRange) < startFunction(inRanges[0]))) {
+      emptyRanges.push(tr.b.Range.fromExplicitRange(
+          startFunction(opt_totalRange), startFunction(inRanges[0])));
+    }
+
+    inRanges.forEach(function(range, index) {
+      for (var otherIndex = 0; otherIndex < inRanges.length; ++otherIndex) {
+        if (index === otherIndex)
+          continue;
+        var other = inRanges[otherIndex];
+
+        if (startFunction(other) > endFunction(range)) {
+          // 'inRanges' is sorted, so 'other' is the first range after 'range',
+          // and there is an empty range between them.
+          emptyRanges.push(tr.b.Range.fromExplicitRange(
+              endFunction(range), startFunction(other)));
+          return;
+        }
+        // Otherwise, 'other' starts before 'range' ends, so 'other' might
+        // possibly contain the end of 'range'.
+
+        if (endFunction(other) > endFunction(range)) {
+          // 'other' does contain the end of 'range', so no empty range starts
+          // at the end of this 'range'.
+          return;
+        }
+      }
+      if (opt_totalRange &&
+          (endFunction(range) < endFunction(opt_totalRange))) {
+        emptyRanges.push(tr.b.Range.fromExplicitRange(
+            endFunction(range), endFunction(opt_totalRange)));
+      }
+    });
+    return emptyRanges;
+  }
+
+  return {
+    findEmptyRangesBetweenExplicitRanges: findEmptyRangesBetweenExplicitRanges,
+    mergeExplicitRanges: mergeExplicitRanges,
+    mergeRanges: mergeRanges
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/extras/audits/utils_test.html b/trace-viewer/trace_viewer/base/range_utils_test.html
similarity index 61%
rename from trace-viewer/trace_viewer/extras/audits/utils_test.html
rename to trace-viewer/trace_viewer/base/range_utils_test.html
index c229af7..824e57a 100644
--- a/trace-viewer/trace_viewer/extras/audits/utils_test.html
+++ b/trace-viewer/trace_viewer/base/range_utils_test.html
@@ -5,13 +5,13 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/extras/audits/utils.html">
+<link rel="import" href="/base/range_utils.html">
 <link rel="import" href="/core/test_utils.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function simpleMerger(events) {
     return {
       start: events[0].start,
@@ -25,7 +25,7 @@
       {start: 200, end: 220}
     ];
 
-    var merged = tv.e.audits.mergeEvents(inEvents, 50, simpleMerger);
+    var merged = tr.e.audits.mergeExplicitRanges(inEvents, 50, simpleMerger);
 
     assert.equal(merged.length, 2);
     assert.deepEqual(merged[0], {start: 0, end: 120});
@@ -39,7 +39,7 @@
       {start: 200, end: 220}
     ];
 
-    var merged = tv.e.audits.mergeEvents(inEvents, 50, simpleMerger);
+    var merged = tr.e.audits.mergeExplicitRanges(inEvents, 50, simpleMerger);
 
     assert.equal(merged.length, 2);
     assert.deepEqual(merged[0], {start: 0, end: 120});
@@ -53,7 +53,7 @@
       {start: 100, end: 120}
     ];
 
-    var merged = tv.e.audits.mergeEvents(inEvents, 50, simpleMerger);
+    var merged = tr.e.audits.mergeExplicitRanges(inEvents, 50, simpleMerger);
 
     assert.equal(merged.length, 1);
     assert.deepEqual(merged[0], {start: 0, end: 120});
@@ -65,7 +65,7 @@
       {start: 150, end: 200}
     ];
 
-    var merged = tv.e.audits.mergeEvents(inEvents, 25, simpleMerger);
+    var merged = tr.e.audits.mergeExplicitRanges(inEvents, 25, simpleMerger);
 
     assert.equal(merged.length, 2);
     assert.deepEqual(merged[0], {start: 0, end: 100});
@@ -78,7 +78,7 @@
     ];
 
     var mergeCount = 0;
-    var merged = tv.e.audits.mergeEvents(inEvents, 25, function(events) {
+    tr.e.audits.mergeExplicitRanges(inEvents, 25, function(events) {
       assert.deepEqual(events, inEvents);
       mergeCount++;
     });
@@ -97,7 +97,7 @@
         end: timestamps[timestamps.length - 1]
       };
     };
-    var merged = tv.e.audits.mergeEvents(inEvents, 15, timestampMerger,
+    var merged = tr.e.audits.mergeExplicitRanges(inEvents, 15, timestampMerger,
                                          identityFunction, identityFunction);
     console.log(merged);
     assert.equal(merged.length, 2);
@@ -105,5 +105,32 @@
     assert.deepEqual(merged[1], {start: 50, end: 60});
   });
 
+  test('findEmptyRangesBetweenExplicitRanges', function() {
+    var events = [
+      {start: 2, end: 4},
+      {start: 1, end: 3},
+      {start: 6, end: 8}
+    ];
+    var ranges = tr.e.audits.findEmptyRangesBetweenExplicitRanges(
+        events, {start: 0, end: 10});
+    assert.equal(3, ranges.length);
+    assert.equal(0, ranges[0].min);
+    assert.equal(1, ranges[0].max);
+    assert.equal(4, ranges[1].min);
+    assert.equal(6, ranges[1].max);
+    assert.equal(8, ranges[2].min);
+    assert.equal(10, ranges[2].max);
+  });
+
+  test('findEmptyRangesWithEmptyInput', function() {
+    var ranges = tr.e.audits.findEmptyRangesBetweenExplicitRanges(
+        [], {start: 0, end: 10});
+    assert.equal(1, ranges.length);
+    assert.equal(0, ranges[0].min);
+    assert.equal(10, ranges[0].max);
+
+    ranges = tr.e.audits.findEmptyRangesBetweenExplicitRanges([]);
+    assert.equal(0, ranges.length);
+  });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/base/rect.html b/trace-viewer/trace_viewer/base/rect.html
index d2e628c..812b36a 100644
--- a/trace-viewer/trace_viewer/base/rect.html
+++ b/trace-viewer/trace_viewer/base/rect.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/base/gl_matrix.html">
+<link rel="import" href="/base/math.html">
 <script>
 'use strict';
 
@@ -13,7 +13,7 @@
  * @fileoverview 2D Rectangle math.
  */
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   /**
    * Tracks a 2D bounding box.
diff --git a/trace-viewer/trace_viewer/base/rect_test.html b/trace-viewer/trace_viewer/base/rect_test.html
index f9bffb0..fb0d513 100644
--- a/trace-viewer/trace_viewer/base/rect_test.html
+++ b/trace-viewer/trace_viewer/base/rect_test.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('UVRectBasic', function() {
     function assertRectEquals(a, b, opt_message) {
       var ok = true;
@@ -18,12 +18,12 @@
       }
       var message = opt_message || 'Expected "' + a.toString() +
           '", got "' + b.toString() + '"';
-      throw new tv.b.unittest.TestError(message);
+      throw new tr.b.unittest.TestError(message);
     }
-    var container = tv.b.Rect.fromXYWH(0, 0, 10, 10);
-    var inner = tv.b.Rect.fromXYWH(1, 1, 8, 8);
+    var container = tr.b.Rect.fromXYWH(0, 0, 10, 10);
+    var inner = tr.b.Rect.fromXYWH(1, 1, 8, 8);
     var uv = inner.asUVRectInside(container);
-    assertRectEquals(uv, tv.b.Rect.fromXYWH(0.1, 0.1, .8, .8));
+    assertRectEquals(uv, tr.b.Rect.fromXYWH(0.1, 0.1, .8, .8));
     assert.equal(10, container.size().width);
     assert.equal(10, container.size().height);
   });
diff --git a/trace-viewer/trace_viewer/base/settings.html b/trace-viewer/trace_viewer/base/settings.html
index c0c6726..10b32ce 100644
--- a/trace-viewer/trace_viewer/base/settings.html
+++ b/trace-viewer/trace_viewer/base/settings.html
@@ -11,19 +11,19 @@
 /**
  * @fileoverview Provides the Settings object.
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   /**
    * Settings is a simple wrapper around local storage, to make it easier
    * to test classes that have settings.
    *
-   * May be called as new tv.b.Settings() or simply tv.b.Settings()
+   * May be called as new tr.b.Settings() or simply tr.b.Settings()
    * @constructor
    */
   function Settings() {
     return Settings;
   };
 
-  document.head.addEventListener('tv-unittest-will-run', function() {
+  document.head.addEventListener('tr-unittest-will-run', function() {
     Settings.setAlternativeStorageInstance(global.sessionStorage);
   });
 
diff --git a/trace-viewer/trace_viewer/base/settings_test.html b/trace-viewer/trace_viewer/base/settings_test.html
index 2d3d4f1..3a17ffb 100644
--- a/trace-viewer/trace_viewer/base/settings_test.html
+++ b/trace-viewer/trace_viewer/base/settings_test.html
@@ -8,49 +8,49 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function assertSettingIs(expectedValue, key) {
-    assert.equal(tv.b.Settings.get(key), expectedValue);
+    assert.equal(tr.b.Settings.get(key), expectedValue);
   }
 
   // Old settings versions used to stringify objects instead of putting them
   // into JSON. This test makes sure that these old settings yield the default
   // value instead of strings.
   test('oldStyleSettingYieldsDefaultValue', function() {
-    var storage = tv.b.Settings.getAlternativeStorageInstance();
-    storage.setItem(tv.b.Settings.namespace_('key'), 'hello world');
+    var storage = tr.b.Settings.getAlternativeStorageInstance();
+    storage.setItem(tr.b.Settings.namespace_('key'), 'hello world');
 
-    assert.equal(tv.b.Settings.get('key', 'value'), 'value');
+    assert.equal(tr.b.Settings.get('key', 'value'), 'value');
   });
 
   test('setGetString', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     settings.set('my_key', 'my_val');
     assert.equal(settings.get('my_key'), 'my_val');
-    // tv.b.Settings() is a singleton
-    assert.equal(tv.b.Settings().get('my_key'), 'my_val');
+    // tr.b.Settings() is a singleton
+    assert.equal(tr.b.Settings().get('my_key'), 'my_val');
   });
 
   test('setGetNumber', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     settings.set('my_key', 5);
     assertSettingIs(5, 'my_key');
   });
 
   test('setGetBool', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     settings.set('my_key', false);
     assertSettingIs(false, 'my_key');
   });
 
   test('setGetObject', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     settings.set('my_key', {'hello': 5});
     assert.deepEqual(settings.get('my_key'), {'hello': 5});
   });
 
   test('setInvalidObject', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     var obj = {'hello': undefined};
     obj.hello = obj;
     assert.throws(function() {
@@ -59,26 +59,26 @@
   });
 
   test('setUndefined', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     assert.throws(function() {
       settings.set('my_key', undefined);
     });
   });
 
   test('getUnset', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     // Undefined should be returned if value isn't set.
     assertSettingIs(undefined, 'my_key');
   });
 
   test('getDefault', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     // default_val should be returned if value isn't set.
     assert.equal(settings.get('my_key', 'default_val'), 'default_val');
   });
 
   test('setGetPrefix', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     settings.set('key_a', 'foo', 'my_prefix');
     assert.equal(settings.get('key_a', undefined, 'my_prefix'), 'foo');
     assert.equal(settings.get('key_a', 'bar', 'my_prefix'), 'foo');
@@ -87,7 +87,7 @@
   });
 
   test('keys', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     settings.set('key_a', 'foo');
     settings.set('key_b', 'bar');
     settings.set('key_c', 'baz');
@@ -95,7 +95,7 @@
   });
 
   test('keysPrefix', function() {
-    var settings = new tv.b.Settings();
+    var settings = new tr.b.Settings();
     settings.set('key_a', 'foo', 'prefix1');
     settings.set('key_b', 'bar', 'prefix1');
     settings.set('key_c', 'baz', 'prefix1');
diff --git a/trace-viewer/trace_viewer/base/sorted_array_utils.html b/trace-viewer/trace_viewer/base/sorted_array_utils.html
index a0f7be5..ae9c3dd 100644
--- a/trace-viewer/trace_viewer/base/sorted_array_utils.html
+++ b/trace-viewer/trace_viewer/base/sorted_array_utils.html
@@ -13,7 +13,7 @@
  * over sorted arrays and intervals.
  *
  */
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   /**
    * Finds the first index in the array whose value is >= loVal.
    *
diff --git a/trace-viewer/trace_viewer/base/sorted_array_utils_test.html b/trace-viewer/trace_viewer/base/sorted_array_utils_test.html
index 95fa151..b99b23b 100644
--- a/trace-viewer/trace_viewer/base/sorted_array_utils_test.html
+++ b/trace-viewer/trace_viewer/base/sorted_array_utils_test.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var ArrayOfIntervals = function(array) {
     this.array = array;
   }
@@ -20,14 +20,14 @@
     },
 
     findLowElementIndex: function(ts) {
-      return tv.b.findLowIndexInSortedArray(
+      return tr.b.findLowIndexInSortedArray(
           this.array,
           function(x) { return x.lo; },
           ts);
     },
 
     findIntervalIndex: function(ts) {
-      return tv.b.findIndexInSortedIntervals(
+      return tr.b.findIndexInSortedIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi - x.lo; },
@@ -35,7 +35,7 @@
     },
 
     findIndexInClosedIntervals: function(ts) {
-      return tv.b.findIndexInSortedClosedIntervals(
+      return tr.b.findIndexInSortedClosedIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi; },
@@ -45,7 +45,7 @@
     findIntersectingIntervals: function(tsA, tsB) {
       var array = this.array;
       var result = [];
-      tv.b.iterateOverIntersectingIntervals(
+      tr.b.iterateOverIntersectingIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi - x.lo; },
@@ -56,7 +56,7 @@
     },
 
     findClosestElement: function(ts, tsDiff) {
-      return tv.b.findClosestElementInSortedArray(
+      return tr.b.findClosestElementInSortedArray(
           this.array,
           function(x) { return x.lo; },
           ts,
@@ -64,7 +64,7 @@
     },
 
     findClosestInterval: function(ts, tsDiff) {
-      return tv.b.findClosestIntervalInSortedIntervals(
+      return tr.b.findClosestIntervalInSortedIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi; },
diff --git a/trace-viewer/trace_viewer/base/statistics.html b/trace-viewer/trace_viewer/base/statistics.html
index a9c6380..8f2148a 100644
--- a/trace-viewer/trace_viewer/base/statistics.html
+++ b/trace-viewer/trace_viewer/base/statistics.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
 
   function identity(d) {
     return d;
@@ -65,7 +65,7 @@
 
   Statistics.range = function(ary, opt_func, opt_this) {
     var func = opt_func || identity;
-    var ret = new tv.b.Range();
+    var ret = new tr.b.Range();
     for (var i = 0; i < ary.length; i++)
       ret.addValue(func.call(opt_this, ary[i], i));
     return ret;
diff --git a/trace-viewer/trace_viewer/base/statistics_test.html b/trace-viewer/trace_viewer/base/statistics_test.html
index 1fd0d2f..3423fee 100644
--- a/trace-viewer/trace_viewer/base/statistics_test.html
+++ b/trace-viewer/trace_viewer/base/statistics_test.html
@@ -8,8 +8,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Statistics = tv.b.Statistics;
+tr.b.unittest.testSuite(function() {
+  var Statistics = tr.b.Statistics;
 
   test('sumBasic', function() {
     assert.equal(Statistics.sum([1, 2, 3]), 6);
diff --git a/trace-viewer/trace_viewer/base/task.html b/trace-viewer/trace_viewer/base/task.html
index d5a7cbc..66892c1 100644
--- a/trace-viewer/trace_viewer/base/task.html
+++ b/trace-viewer/trace_viewer/base/task.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   /**
    * A task is a combination of a run callback, a set of subtasks, and an after
    * task.
@@ -91,6 +91,16 @@
       else
         this.afterTask_ = new Task(cb, thisArg);
       return this.afterTask_;
+    },
+
+    /*
+     * Adds a task after the chain of tasks.
+     */
+    enqueue: function(cb, thisArg) {
+      var lastTask = this;
+      while (lastTask.afterTask_)
+        lastTask = lastTask.afterTask_;
+      return lastTask.after(cb, thisArg);
     }
   };
 
@@ -117,13 +127,13 @@
         }
 
         if (curTask) {
-          tv.b.requestIdleCallback(runAnother);
+          tr.b.requestIdleCallback(runAnother);
           return;
         }
 
         resolve();
       }
-      tv.b.requestIdleCallback(runAnother);
+      tr.b.requestIdleCallback(runAnother);
     });
   }
 
diff --git a/trace-viewer/trace_viewer/base/task_test.html b/trace-viewer/trace_viewer/base/task_test.html
index 9eac8dd..84b60e2 100644
--- a/trace-viewer/trace_viewer/base/task_test.html
+++ b/trace-viewer/trace_viewer/base/task_test.html
@@ -9,8 +9,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Task = tv.b.Task;
+tr.b.unittest.testSuite(function() {
+  var Task = tr.b.Task;
 
   test('basicAllStepsPass', function() {
     var results = [];
diff --git a/trace-viewer/trace_viewer/base/tests.html b/trace-viewer/trace_viewer/base/tests.html
index 54fa2f5..c64e1f8 100644
--- a/trace-viewer/trace_viewer/base/tests.html
+++ b/trace-viewer/trace_viewer/base/tests.html
@@ -95,7 +95,7 @@
       }
 
       showLoadingOverlay();
-      var loader = new tv.b.unittest.SuiteLoader(suiteNamesToLoad);
+      var loader = new tr.b.unittest.SuiteLoader(suiteNamesToLoad);
       return loader.allSuitesLoadedPromise.then(
         function() {
           hideLoadingOverlay();
@@ -105,7 +105,7 @@
         },
         function(err) {
           hideLoadingOverlay();
-          tv.showPanic('Module loading failure', err);
+          tr.showPanic('Module loading failure', err);
           throw err;
         });
     }
@@ -162,7 +162,7 @@
     }
 
     function runTests(loader, state) {
-      var runner = new tv.b.unittest.InteractiveTestRunner();
+      var runner = new tr.b.unittest.InteractiveTestRunner();
       runner.testLinks = loader.testLinks;
       runner.allTests = loader.getAllTests();
       document.body.appendChild(runner);
diff --git a/trace-viewer/trace_viewer/base/ui.html b/trace-viewer/trace_viewer/base/ui.html
index 2b710e0..48bacc2 100644
--- a/trace-viewer/trace_viewer/base/ui.html
+++ b/trace-viewer/trace_viewer/base/ui.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   /**
    * Decorates elements as an instance of a class.
@@ -21,7 +21,7 @@
   function decorate(source, constr) {
     var elements;
     if (typeof source == 'string')
-      elements = tv.doc.querySelectorAll(source);
+      elements = tr.doc.querySelectorAll(source);
     else
       elements = [source];
 
@@ -35,8 +35,8 @@
    * Defines a tracing UI component, a function that can be called to construct
    * the component.
    *
-   * tv class:
-   * var List = tv.b.ui.define('list');
+   * tr class:
+   * var List = tr.b.ui.define('list');
    * List.prototype = {
    *   __proto__: HTMLUListElement.prototype,
    *   decorate: function() {
@@ -46,7 +46,7 @@
    * };
    *
    * Derived class:
-   * var CustomList = tv.b.ui.define('custom-list', List);
+   * var CustomList = tr.b.ui.define('custom-list', List);
    * CustomList.prototype = {
    *   __proto__: List.prototype,
    *   decorate: function() {
@@ -62,7 +62,7 @@
 
    * @param {function=} opt_parentConstructor The parent class for this new
    *     element, if subclassing is desired. If provided, the parent class must
-   *     be also a function created by tv.b.ui.define.
+   *     be also a function created by tr.b.ui.define.
    *
    * @param {string=} opt_tagNS The namespace in which to create the base
    *     element. Has no meaning when opt_parentConstructor is passed and must
@@ -80,7 +80,7 @@
     var className = className.toLowerCase();
     if (opt_parentConstructor && !opt_parentConstructor.tagName)
       throw new Error('opt_parentConstructor was not ' +
-                      'created by tv.b.ui.define');
+                      'created by tr.b.ui.define');
 
     // Walk up the parent constructors until we can find the type of tag
     // to create.
@@ -116,9 +116,9 @@
 
       var el;
       if (tagNS === undefined)
-        el = tv.doc.createElement(tagName);
+        el = tr.doc.createElement(tagName);
       else
-        el = tv.doc.createElementNS(tagNS, tagName);
+        el = tr.doc.createElementNS(tagNS, tagName);
       f.decorate.call(this, el, arguments);
       return el;
     }
diff --git a/trace-viewer/trace_viewer/base/ui/animation.html b/trace-viewer/trace_viewer/base/ui/animation.html
index 4e86daa..ff984ee 100644
--- a/trace-viewer/trace_viewer/base/ui/animation.html
+++ b/trace-viewer/trace_viewer/base/ui/animation.html
@@ -8,10 +8,10 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   /**
    * Represents a procedural animation that can be run by an
-   * tv.b.ui.AnimationController.
+   * tr.b.ui.AnimationController.
    *
    * @constructor
    */
diff --git a/trace-viewer/trace_viewer/base/ui/animation_controller.html b/trace-viewer/trace_viewer/base/ui/animation_controller.html
index 3080b8e..30baee5 100644
--- a/trace-viewer/trace_viewer/base/ui/animation_controller.html
+++ b/trace-viewer/trace_viewer/base/ui/animation_controller.html
@@ -10,19 +10,19 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   /**
-   * Manages execution, queueing and blending of tv.b.ui.Animations against
+   * Manages execution, queueing and blending of tr.b.ui.Animations against
    * a single target.
    *
    * Targets must have a cloneAnimationState() method that returns all the
    * animatable states of that target.
    *
    * @constructor
-   * @extends {tv.b.EventTarget}
+   * @extends {tr.b.EventTarget}
    */
   function AnimationController() {
-    tv.b.EventTarget.call(this);
+    tr.b.EventTarget.call(this);
 
     this.target_ = undefined;
 
@@ -32,7 +32,7 @@
   }
 
   AnimationController.prototype = {
-    __proto__: tv.b.EventTarget.prototype,
+    __proto__: tr.b.EventTarget.prototype,
 
     get target() {
       return this.target_;
@@ -89,7 +89,7 @@
       if (this.tickScheduled_)
         return;
       this.tickScheduled_ = true;
-      tv.b.requestAnimationFrame(this.tickActiveAnimation_, this);
+      tr.b.requestAnimationFrame(this.tickActiveAnimation_, this);
     },
 
     cancelActiveAnimation: function(opt_now) {
@@ -122,7 +122,7 @@
 
       if (this.activeAnimation_) {
         this.tickScheduled_ = true;
-        tv.b.requestAnimationFrame(this.tickActiveAnimation_, this);
+        tr.b.requestAnimationFrame(this.tickActiveAnimation_, this);
       }
 
       if (oldTargetState) {
diff --git a/trace-viewer/trace_viewer/base/ui/animation_controller_test.html b/trace-viewer/trace_viewer/base/ui/animation_controller_test.html
index 13662fb..cc2fade 100644
--- a/trace-viewer/trace_viewer/base/ui/animation_controller_test.html
+++ b/trace-viewer/trace_viewer/base/ui/animation_controller_test.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function SimpleAnimation(options) {
     this.stopTime = options.stopTime;
 
@@ -20,7 +20,7 @@
   }
 
   SimpleAnimation.prototype = {
-    __proto__: tv.b.ui.Animation.prototype,
+    __proto__: tr.b.ui.Animation.prototype,
 
     canTakeOverFor: function(existingAnimation) {
       return false;
@@ -54,13 +54,13 @@
       cloneAnimationState: function() { return {x: this.x}; }
     };
 
-    var controller = new tv.b.ui.AnimationController();
+    var controller = new tr.b.ui.AnimationController();
     controller.target = target;
 
     var animation = new SimpleAnimation({stopTime: 100});
     controller.queueAnimation(animation);
 
-    tv.b.forcePendingRAFTasksToRun(0);
+    tr.b.forcePendingRAFTasksToRun(0);
     assert.equal(animation.tickCount, 1);
     controller.cancelActiveAnimation();
     assert.isFalse(controller.hasActiveAnimation);
@@ -73,31 +73,31 @@
       cloneAnimationState: function() { return {x: this.x}; }
     };
 
-    var controller = new tv.b.ui.AnimationController();
+    var controller = new tr.b.ui.AnimationController();
     controller.target = target;
 
     var animation = new SimpleAnimation({stopTime: 100});
     controller.queueAnimation(animation);
 
-    tv.b.forcePendingRAFTasksToRun(0);
+    tr.b.forcePendingRAFTasksToRun(0);
     assert.equal(animation.tickCount, 1);
     assert.isTrue(controller.hasActiveAnimation);
 
-    tv.b.forcePendingRAFTasksToRun(100);
+    tr.b.forcePendingRAFTasksToRun(100);
     assert.equal(animation.tickCount, 2);
     assert.isFalse(controller.hasActiveAnimation);
   });
 
   test('queueTwo', function() {
     // Clear all pending rafs so if something is lingering it will blow up here.
-    tv.b.forcePendingRAFTasksToRun(0);
+    tr.b.forcePendingRAFTasksToRun(0);
 
     var target = {
       x: 0,
       cloneAnimationState: function() { return {x: this.x}; }
     };
 
-    var controller = new tv.b.ui.AnimationController();
+    var controller = new tr.b.ui.AnimationController();
     controller.target = target;
 
     var a1 = new SimpleAnimation({stopTime: 100});
@@ -108,7 +108,7 @@
     assert.isTrue(a1.didStopEarlyCalled);
     assert.isTrue(a2.startCalled);
 
-    tv.b.forcePendingRAFTasksToRun(150);
+    tr.b.forcePendingRAFTasksToRun(150);
     assert.isFalse(controller.hasActiveAnimation);
     assert.isAbove(a2.tickCount, 0);
   });
@@ -121,7 +121,7 @@
   }
 
   AnimationThatCanTakeOverForSimpleAnimation.prototype = {
-    __proto__: tv.b.ui.Animation.prototype,
+    __proto__: tr.b.ui.Animation.prototype,
 
 
     canTakeOverFor: function(existingAnimation) {
@@ -143,7 +143,7 @@
       cloneAnimationState: function() { return {x: this.x}; }
     };
 
-    var controller = new tv.b.ui.AnimationController();
+    var controller = new tr.b.ui.AnimationController();
     controller.target = target;
 
     var a1 = new SimpleAnimation({stopTime: 100});
diff --git a/trace-viewer/trace_viewer/base/ui/camera.html b/trace-viewer/trace_viewer/base/ui/camera.html
index ad17b27..2166933 100644
--- a/trace-viewer/trace_viewer/base/ui/camera.html
+++ b/trace-viewer/trace_viewer/base/ui/camera.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   var constants = {
     DEFAULT_SCALE: 0.5,
@@ -19,11 +19,11 @@
     FOV: 15,
     RESCALE_TIMEOUT_MS: 200,
     MAXIMUM_TILT: 80,
-    SETTINGS_NAMESPACE: 'tv.ui_camera'
+    SETTINGS_NAMESPACE: 'tr.ui_camera'
   };
 
 
-  var Camera = tv.b.ui.define('camera');
+  var Camera = tr.b.ui.define('camera');
 
   Camera.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -69,12 +69,12 @@
 
     get projectionMatrix() {
       var rect =
-          tv.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);
+          tr.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);
 
       var aspectRatio = rect.width / rect.height;
       var matrix = mat4.create();
       mat4.perspective(
-          matrix, tv.b.deg2rad(constants.FOV), aspectRatio, 1, 100000);
+          matrix, tr.b.deg2rad(constants.FOV), aspectRatio, 1, 100000);
 
       return matrix;
     },
@@ -121,7 +121,7 @@
       this.gazeTarget_ = [0, 0, 0];
       this.rotation_ = [0, 0];
 
-      var settings = tv.b.SessionSettings();
+      var settings = tr.b.SessionSettings();
       var keys = settings.keys(constants.SETTINGS_NAMESPACE);
       if (keys.length !== 0) {
         this.loadCameraFromSettings(settings);
@@ -130,7 +130,7 @@
 
       if (this.deviceRect_) {
         var rect =
-            tv.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);
+            tr.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);
 
         this.eye_[0] = this.deviceRect_.width / 2;
         this.eye_[1] = this.deviceRect_.height / 2;
@@ -145,7 +145,7 @@
 
     updatePanByDelta: function(delta) {
       var rect =
-          tv.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);
+          tr.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);
 
       // Get the eye vector, since we'll be adjusting gazeTarget.
       var eyeVector = [
@@ -157,15 +157,15 @@
 
       var halfFov = constants.FOV / 2;
       var multiplier =
-          2.0 * length * Math.tan(tv.b.deg2rad(halfFov)) / rect.height;
+          2.0 * length * Math.tan(tr.b.deg2rad(halfFov)) / rect.height;
 
       // Get the up and right vectors.
       var up = [0, 1, 0];
       var rotMatrix = mat4.create();
       mat4.rotate(
-          rotMatrix, rotMatrix, tv.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
+          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
       mat4.rotate(
-          rotMatrix, rotMatrix, tv.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
+          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
       vec3.transformMat4(up, up, rotMatrix);
 
       var right = [0, 0, 0];
@@ -184,7 +184,7 @@
       // to be on the plane z = 0 with normal [0, 0, 1].
       if (Math.abs(this.gazeTarget_[2]) > 1e-6) {
         var gazeVector = [-eyeVector[0], -eyeVector[1], -eyeVector[2]];
-        var newLength = tv.b.clamp(
+        var newLength = tr.b.clamp(
             -this.eye_[2] / gazeVector[2],
             constants.MINIMUM_DISTANCE,
             constants.MAXIMUM_DISTANCE);
@@ -193,13 +193,13 @@
           this.gazeTarget_[i] = this.eye_[i] + newLength * gazeVector[i];
       }
 
-      this.saveCameraToSettings(tv.b.SessionSettings());
+      this.saveCameraToSettings(tr.b.SessionSettings());
       this.dispatchRenderEvent_();
     },
 
     updateZoomByDelta: function(delta) {
       var deltaY = delta[1];
-      deltaY = tv.b.clamp(deltaY, -50, 50);
+      deltaY = tr.b.clamp(deltaY, -50, 50);
       var scale = 1.0 - deltaY / 100.0;
 
       var eyeVector = [0, 0, 0];
@@ -216,7 +216,7 @@
       vec3.scale(eyeVector, eyeVector, scale);
       vec3.add(this.eye_, this.gazeTarget_, eyeVector);
 
-      this.saveCameraToSettings(tv.b.SessionSettings());
+      this.saveCameraToSettings(tr.b.SessionSettings());
       this.dispatchRenderEvent_();
     },
 
@@ -235,9 +235,9 @@
       // Undo the current rotation.
       var rotMatrix = mat4.create();
       mat4.rotate(
-          rotMatrix, rotMatrix, -tv.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
+          rotMatrix, rotMatrix, -tr.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
       mat4.rotate(
-          rotMatrix, rotMatrix, -tv.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
+          rotMatrix, rotMatrix, -tr.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
       vec4.transformMat4(eyeVector, eyeVector, rotMatrix);
 
       // Update rotation values.
@@ -247,14 +247,14 @@
       // Redo the new rotation.
       mat4.identity(rotMatrix);
       mat4.rotate(
-          rotMatrix, rotMatrix, tv.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
+          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
       mat4.rotate(
-          rotMatrix, rotMatrix, tv.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
+          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
       vec4.transformMat4(eyeVector, eyeVector, rotMatrix);
 
       vec3.add(this.eye_, this.gazeTarget_, eyeVector);
 
-      this.saveCameraToSettings(tv.b.SessionSettings());
+      this.saveCameraToSettings(tr.b.SessionSettings());
       this.dispatchRenderEvent_();
     },
 
@@ -322,7 +322,7 @@
 
     // Misc helper functions.
     getMousePosition_: function(e) {
-      var rect = tv.b.windowRectForElement(this.canvas_);
+      var rect = tr.b.windowRectForElement(this.canvas_);
       return [(e.clientX - rect.x) * this.pixelRatio_,
               (e.clientY - rect.y) * this.pixelRatio_];
     },
@@ -333,7 +333,7 @@
     },
 
     dispatchRenderEvent_: function() {
-      tv.b.dispatchSimpleEvent(this, 'renderrequired', false, false);
+      tr.b.dispatchSimpleEvent(this, 'renderrequired', false, false);
     }
   };
 
diff --git a/trace-viewer/trace_viewer/base/ui/camera_test.html b/trace-viewer/trace_viewer/base/ui/camera_test.html
index 751a89d..71dfba8 100644
--- a/trace-viewer/trace_viewer/base/ui/camera_test.html
+++ b/trace-viewer/trace_viewer/base/ui/camera_test.html
@@ -11,18 +11,18 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
   function createQuads() {
     var quads = [
-      tv.b.Quad.fromXYWH(-500, -500, 30, 30), // 4 corners
-      tv.b.Quad.fromXYWH(-500, 470, 30, 30),
-      tv.b.Quad.fromXYWH(470, -500, 30, 30),
-      tv.b.Quad.fromXYWH(470, 470, 30, 30),
-      tv.b.Quad.fromXYWH(-250, -250, 250, 250), // crosshairs
-      tv.b.Quad.fromXYWH(0, -250, 250, 250), // crosshairs
-      tv.b.Quad.fromXYWH(-250, 0, 250, 250), // crosshairs
-      tv.b.Quad.fromXYWH(0, 0, 250, 250) // crosshairs
+      tr.b.Quad.fromXYWH(-500, -500, 30, 30), // 4 corners
+      tr.b.Quad.fromXYWH(-500, 470, 30, 30),
+      tr.b.Quad.fromXYWH(470, -500, 30, 30),
+      tr.b.Quad.fromXYWH(470, 470, 30, 30),
+      tr.b.Quad.fromXYWH(-250, -250, 250, 250), // crosshairs
+      tr.b.Quad.fromXYWH(0, -250, 250, 250), // crosshairs
+      tr.b.Quad.fromXYWH(-250, 0, 250, 250), // crosshairs
+      tr.b.Quad.fromXYWH(0, 0, 250, 250) // crosshairs
     ];
     quads[0].stackingGroupId = 0;
     quads[1].stackingGroupId = 0;
@@ -37,11 +37,11 @@
 
   function createQuadStackView(testFramework) {
     var quads = createQuads();
-    var view = new tv.b.ui.QuadStackView();
+    var view = new tr.b.ui.QuadStackView();
     // simulate the constraints of the layer-tree-view
     view.style.height = '400px';
     view.style.width = '800px';
-    view.deviceRect = tv.b.Rect.fromXYWH(-250, -250, 500, 500);
+    view.deviceRect = tr.b.Rect.fromXYWH(-250, -250, 500, 500);
     view.quads = quads;
 
     testFramework.addHTMLOutput(view);
diff --git a/trace-viewer/trace_viewer/base/ui/chart_base.html b/trace-viewer/trace_viewer/base/ui/chart_base.html
index cf2ee65..6aba25c 100644
--- a/trace-viewer/trace_viewer/base/ui/chart_base.html
+++ b/trace-viewer/trace_viewer/base/ui/chart_base.html
@@ -40,17 +40,17 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
   var svgNS = 'http://www.w3.org/2000/svg';
-  var highlightIdBoost = tv.b.ui.getColorPaletteHighlightIdBoost();
+  var highlightIdBoost = tr.b.ui.getColorPaletteHighlightIdBoost();
 
   function getColorOfKey(key, selected) {
-    var id = tv.b.ui.getColorIdForGeneralPurposeString(key);
+    var id = tr.b.ui.getColorIdForGeneralPurposeString(key);
     if (selected)
       id += highlightIdBoost;
-    return tv.b.ui.getColorPalette()[id];
+    return tr.b.ui.getColorPalette()[id];
   }
 
   /**
@@ -59,7 +59,7 @@
    *
    * @constructor
    */
-  var ChartBase = tv.b.ui.define('svg', undefined, svgNS);
+  var ChartBase = tr.b.ui.define('svg', undefined, svgNS);
 
   ChartBase.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -72,7 +72,7 @@
       this.width_ = 400;
       this.height_ = 300;
 
-      // This should use tv.b.instantiateTemplate. However, creating
+      // This should use tr.b.instantiateTemplate. However, creating
       // svg-namespaced elements inside a template isn't possible. Thus, this
       // hack.
       var template = THIS_DOC.querySelector('#chart-base-template');
diff --git a/trace-viewer/trace_viewer/base/ui/color_legend.html b/trace-viewer/trace_viewer/base/ui/color_legend.html
index 193e789..0498ca9 100644
--- a/trace-viewer/trace_viewer/base/ui/color_legend.html
+++ b/trace-viewer/trace_viewer/base/ui/color_legend.html
@@ -10,14 +10,19 @@
 <!--
 @fileoverview A component used to display a label preceded by a small square
 filled with the label's associated color (as determined by
-tv.b.ui.getColorIdForGeneralPurposeString).
+tr.b.ui.getColorIdForGeneralPurposeString).
 -->
-<polymer-element name="tv-b-color-legend">
+<polymer-element name="tr-b-ui-color-legend">
   <template>
     <style>
     :host {
       display: inline-block;
     }
+
+    #square {
+      font-size: 150%;  /* Make the square bigger. */
+      line-height: 0%;  /* Prevent the square from increasing legend height. */
+    }
     </style>
     <span id="square"></span>
     <span id="label"></span>
@@ -27,8 +32,8 @@
 
   Polymer({
     ready: function() {
-      var blackLargeSquareCharCode = 11035;
-      this.$.square.innerText = String.fromCharCode(blackLargeSquareCharCode);
+      var blackSquareCharCode = 9632;
+      this.$.square.innerText = String.fromCharCode(blackSquareCharCode);
       this.label_ = undefined;
     },
 
@@ -45,9 +50,9 @@
         return;
       }
 
-      var paletteRaw = tv.b.ui.getRawColorPalette();
-      var colorId = tv.b.ui.getColorIdForGeneralPurposeString(this.label_);
-      var color = tv.b.ui.colorToRGBString(paletteRaw[colorId]);
+      var paletteRaw = tr.b.ui.getRawColorPalette();
+      var colorId = tr.b.ui.getColorIdForGeneralPurposeString(this.label_);
+      var color = tr.b.ui.colorToRGBString(paletteRaw[colorId]);
       this.$.square.style.color = color;
       this.$.label.innerText = this.label_;
     }
diff --git a/trace-viewer/trace_viewer/base/ui/color_legend_test.html b/trace-viewer/trace_viewer/base/ui/color_legend_test.html
index 848fd39..e909ce1 100644
--- a/trace-viewer/trace_viewer/base/ui/color_legend_test.html
+++ b/trace-viewer/trace_viewer/base/ui/color_legend_test.html
@@ -10,29 +10,29 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
     // No label set.
-    var colorLegend = document.createElement('tv-b-color-legend');
+    var colorLegend = document.createElement('tr-b-ui-color-legend');
     this.addHTMLOutput(colorLegend);
 
     // Undefined label.
-    var colorLegend = document.createElement('tv-b-color-legend');
+    var colorLegend = document.createElement('tr-b-ui-color-legend');
     colorLegend.label = undefined;
     this.addHTMLOutput(colorLegend);
 
     // Empty label.
-    var colorLegend = document.createElement('tv-b-color-legend');
+    var colorLegend = document.createElement('tr-b-ui-color-legend');
     colorLegend.label = '';
     this.addHTMLOutput(colorLegend);
 
     // Non-empty label.
-    var colorLegend = document.createElement('tv-b-color-legend');
+    var colorLegend = document.createElement('tr-b-ui-color-legend');
     colorLegend.label = 'Frequency';
     this.addHTMLOutput(colorLegend);
 
     // Long label.
-    var colorLegend = document.createElement('tv-b-color-legend');
+    var colorLegend = document.createElement('tr-b-ui-color-legend');
     colorLegend.label = 'Total memory usage';
     this.addHTMLOutput(colorLegend);
   });
diff --git a/trace-viewer/trace_viewer/base/ui/color_scheme.html b/trace-viewer/trace_viewer/base/ui/color_scheme.html
index 7c46eb4..fe4810c 100644
--- a/trace-viewer/trace_viewer/base/ui/color_scheme.html
+++ b/trace-viewer/trace_viewer/base/ui/color_scheme.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Provides color scheme related functions.
  */
-tv.exportTo('tv.b.ui', function() {
-  var colorToRGBString = tv.b.ui.colorToRGBString;
-  var colorToRGBAString = tv.b.ui.colorToRGBAString;
+tr.exportTo('tr.b.ui', function() {
+  var colorToRGBString = tr.b.ui.colorToRGBString;
+  var colorToRGBAString = tr.b.ui.colorToRGBAString;
 
   // Basic constants...
 
@@ -66,12 +66,17 @@
     bad: {r: 180, g: 125, b: 0},
     terrible: {r: 180, g: 0, b: 0},
 
-    black: {r: 0, g: 0, b: 0}
+    black: {r: 0, g: 0, b: 0},
+
+    rail_response: {r: 67, g: 135, b: 253},
+    rail_animate: {r: 244, g: 74, b: 63},
+    rail_idle: {r: 238, g: 142, b: 0},
+    rail_load: {r: 13, g: 168, b: 97}
   };
 
   // Some constants we'll need for later lookups.
   var numGeneralPurposeColorIds = generalPurposeColors.length;
-  var numReservedColorIds = tv.b.dictionaryLength(reservedColorsByName);
+  var numReservedColorIds = tr.b.dictionaryLength(reservedColorsByName);
 
   // The color palette is split in half, with the upper
   // half of the palette being the "highlighted" verison
@@ -89,9 +94,9 @@
     var paletteBase = [];
     paletteBase.push.apply(paletteBase, generalPurposeColors);
     paletteBase.push.apply(paletteBase,
-                           tv.b.dictionaryValues(reservedColorsByName));
-    return paletteBase.concat(paletteBase.map(tv.b.ui.brightenColor),
-                              paletteBase.map(tv.b.ui.desaturateColor));
+                           tr.b.dictionaryValues(reservedColorsByName));
+    return paletteBase.concat(paletteBase.map(tr.b.ui.brightenColor),
+                              paletteBase.map(tr.b.ui.desaturateColor));
   })();
   var palette = paletteRaw.map(colorToRGBString);
 
@@ -102,7 +107,7 @@
   var reservedColorNameToIdMap = (function() {
     var m = {};
     var i = generalPurposeColors.length;
-    tv.b.iterItems(reservedColorsByName, function(key, value) {
+    tr.b.iterItems(reservedColorsByName, function(key, value) {
       m[key] = i++;
     });
     return m;
diff --git a/trace-viewer/trace_viewer/base/ui/color_scheme_test.html b/trace-viewer/trace_viewer/base/ui/color_scheme_test.html
index d7c1b86..fb1fd3d 100644
--- a/trace-viewer/trace_viewer/base/ui/color_scheme_test.html
+++ b/trace-viewer/trace_viewer/base/ui/color_scheme_test.html
@@ -10,15 +10,15 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var brighten = tv.b.ui.brightenColor;
-  var desaturate = tv.b.ui.desaturateColor;
+tr.b.unittest.testSuite(function() {
+  var brighten = tr.b.ui.brightenColor;
+  var desaturate = tr.b.ui.desaturateColor;
 
   test('buildColorPalette', function() {
-    var palette = tv.b.ui.getColorPalette();
-    var rawPalette = tv.b.ui.getRawColorPalette();
-    var highlightOffset = tv.b.ui.getColorPaletteHighlightIdBoost();
-    var desaturateOffset = tv.b.ui.getColorPaletteDesaturateIdBoost();
+    var palette = tr.b.ui.getColorPalette();
+    var rawPalette = tr.b.ui.getRawColorPalette();
+    var highlightOffset = tr.b.ui.getColorPaletteHighlightIdBoost();
+    var desaturateOffset = tr.b.ui.getColorPaletteDesaturateIdBoost();
 
     assert.strictEqual(palette.length, rawPalette.length);
     assert.equal(palette.length % 3, 0);
diff --git a/trace-viewer/trace_viewer/base/ui/color_utils.html b/trace-viewer/trace_viewer/base/ui/color_utils.html
index 8f2d3e1..fe22791 100644
--- a/trace-viewer/trace_viewer/base/ui/color_utils.html
+++ b/trace-viewer/trace_viewer/base/ui/color_utils.html
@@ -11,7 +11,7 @@
 /**
  * @fileoverview Provides color scheme related functions.
  */
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   function boundChannel(v) {
     return Math.min(255, Math.max(0, Math.floor(v)));
diff --git a/trace-viewer/trace_viewer/base/ui/common.css b/trace-viewer/trace_viewer/base/ui/common.css
index ee06a62..40991c2 100644
--- a/trace-viewer/trace_viewer/base/ui/common.css
+++ b/trace-viewer/trace_viewer/base/ui/common.css
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* Global TVCM CSS values, applied application-wide */
+/* Global CSS values, applied application-wide */
 
 body * {
   -webkit-user-select: none;
diff --git a/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children.html b/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children.html
index 86ee86f..9fcb1ac 100644
--- a/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children.html
+++ b/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children.html
@@ -12,11 +12,11 @@
 /**
  * @fileoverview Container that decorates its children.
  */
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   /**
    * @constructor
    */
-  var ContainerThatDecoratesItsChildren = tv.b.ui.define('div');
+  var ContainerThatDecoratesItsChildren = tr.b.ui.define('div');
 
   ContainerThatDecoratesItsChildren.prototype = {
     __proto__: HTMLUnknownElement.prototype,
diff --git a/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children_test.html b/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children_test.html
index bc96feb..cbd3cb2 100644
--- a/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children_test.html
+++ b/trace-viewer/trace_viewer/base/ui/container_that_decorates_its_children_test.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
 
   function createChild() {
     var span = document.createElement('span');
@@ -19,11 +19,11 @@
   /**
    * @constructor
    */
-  var SimpleContainer = tv.b.ui.define(
-      'simple-container', tv.b.ui.ContainerThatDecoratesItsChildren);
+  var SimpleContainer = tr.b.ui.define(
+      'simple-container', tr.b.ui.ContainerThatDecoratesItsChildren);
 
   SimpleContainer.prototype = {
-    __proto__: tv.b.ui.ContainerThatDecoratesItsChildren.prototype,
+    __proto__: tr.b.ui.ContainerThatDecoratesItsChildren.prototype,
 
     decorateChild_: function(child) {
       assert.isFalse(child.decorated);
diff --git a/trace-viewer/trace_viewer/base/ui/dom_helpers.html b/trace-viewer/trace_viewer/base/ui/dom_helpers.html
index 001f238..5490dd2 100644
--- a/trace-viewer/trace_viewer/base/ui/dom_helpers.html
+++ b/trace-viewer/trace_viewer/base/ui/dom_helpers.html
@@ -15,7 +15,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   function createSpan(opt_dictionary) {
     var spanEl = document.createElement('span');
@@ -92,7 +92,7 @@
     }
     function onChange(e) {
       var value = selectorEl.selectedOptions[0].targetPropertyValue;
-      tv.b.Settings.set(settingsKey, value, opt_namespace);
+      tr.b.Settings.set(settingsKey, value, opt_namespace);
       targetEl[targetElProperty] = value;
     }
     var oldSetter = targetEl.__lookupSetter__('selectedIndex');
@@ -114,7 +114,7 @@
       throw new Error('Not a valid value');
     });
 
-    var initialValue = tv.b.Settings.get(
+    var initialValue = tr.b.Settings.get(
         settingsKey, defaultValue, opt_namespace);
     var didSet = false;
     for (var i = 0; i < selectorEl.children.length; i++) {
@@ -152,12 +152,12 @@
       var value = [];
       if (this.value.length)
         value = this.value.split(',');
-      tv.b.Settings.set(settingsKey, value);
+      tr.b.Settings.set(settingsKey, value);
       targetEl[targetElProperty] = value;
     }
 
     var optionGroupEl = createSpan({className: 'labeled-option-group'});
-    var initialValue = tv.b.Settings.get(settingsKey, defaultValue);
+    var initialValue = tr.b.Settings.get(settingsKey, defaultValue);
     for (var i = 0; i < items.length; ++i) {
       var item = items[i];
       var id = 'category-preset-' + item.label.replace(/ /g, '-');
@@ -214,13 +214,13 @@
     var buttonEl = document.createElement('input');
     buttonEl.type = 'checkbox';
 
-    var initialValue = tv.b.Settings.get(settingsKey, defaultValue);
+    var initialValue = tr.b.Settings.get(settingsKey, defaultValue);
     buttonEl.checked = !!initialValue;
     if (targetEl)
       targetEl[targetElProperty] = initialValue;
 
     function onChange() {
-      tv.b.Settings.set(settingsKey, buttonEl.checked);
+      tr.b.Settings.set(settingsKey, buttonEl.checked);
       if (targetEl)
         targetEl[targetElProperty] = buttonEl.checked;
     }
diff --git a/trace-viewer/trace_viewer/base/ui/dom_helpers_test.html b/trace-viewer/trace_viewer/base/ui/dom_helpers_test.html
index 4ed278d..cc66a7f 100644
--- a/trace-viewer/trace_viewer/base/ui/dom_helpers_test.html
+++ b/trace-viewer/trace_viewer/base/ui/dom_helpers_test.html
@@ -8,14 +8,14 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
   test('simpleSpanAndDiv', function() {
-    var divEl = tv.b.ui.createDiv({
+    var divEl = tr.b.ui.createDiv({
       className: 'a-div-class', parent: document.body
     });
     var testText = 'some span text';
-    var spanEl = tv.b.ui.createSpan({
+    var spanEl = tr.b.ui.createSpan({
       className: 'a-span-class',
       textContent: testText,
       parent: divEl
@@ -27,33 +27,33 @@
 
   test('checkboxFromDefaults', function() {
     var target = {foo: undefined};
-    var cb = tv.b.ui.createCheckBox(target, 'foo', 'myCheckBox', false, 'Foo');
+    var cb = tr.b.ui.createCheckBox(target, 'foo', 'myCheckBox', false, 'Foo');
     assert.isFalse(target.foo);
   });
 
   test('checkboxFromSettings', function() {
-    tv.b.Settings.set('myCheckBox', true);
+    tr.b.Settings.set('myCheckBox', true);
     var target = {foo: undefined};
-    var cb = tv.b.ui.createCheckBox(target, 'foo', 'myCheckBox', false, 'Foo');
+    var cb = tr.b.ui.createCheckBox(target, 'foo', 'myCheckBox', false, 'Foo');
     assert.isTrue(target.foo);
   });
 
   test('checkboxChanged', function() {
     var target = {foo: undefined};
-    var cb = tv.b.ui.createCheckBox(target, 'foo', 'myCheckBox', false, 'Foo');
+    var cb = tr.b.ui.createCheckBox(target, 'foo', 'myCheckBox', false, 'Foo');
     cb.checked = true;
 
-    assert.isTrue(tv.b.Settings.get('myCheckBox', undefined));
+    assert.isTrue(tr.b.Settings.get('myCheckBox', undefined));
     assert.isTrue(target.foo);
   });
 
   test('selectorSettingsAlreaySet', function() {
-    tv.b.Settings.set('myScale', 0.25);
+    tr.b.Settings.set('myScale', 0.25);
 
     var target = {
       scale: 314
     };
-    var sel = tv.b.ui.createSelector(
+    var sel = tr.b.ui.createSelector(
         target, 'scale',
         'myScale', 0.375,
         [{label: '6.25%', value: 0.0625},
@@ -73,7 +73,7 @@
     var target = {
       scale: 314
     };
-    var sel = tv.b.ui.createSelector(
+    var sel = tr.b.ui.createSelector(
         target, 'scale',
         'myScale', 0.375,
         [{label: '6.25%', value: 0.0625},
@@ -93,7 +93,7 @@
     var target = {
       scale: 314
     };
-    var sel = tv.b.ui.createSelector(
+    var sel = tr.b.ui.createSelector(
         target, 'scale',
         'myScale', 0.375,
         [{label: '6.25%', value: 0.0625},
@@ -109,7 +109,7 @@
     sel.selectedValue = 0.75;
     assert.equal(target.scale, 0.75);
     assert.equal(sel.selectedValue, 0.75);
-    assert.equal(undefined), 0.75, tv.b.Settings.get('myScale');
+    assert.equal(undefined), 0.75, tr.b.Settings.get('myScale');
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/base/ui/drag_handle.html b/trace-viewer/trace_viewer/base/ui/drag_handle.html
index 4c2a466..c9933e2 100644
--- a/trace-viewer/trace_viewer/base/ui/drag_handle.html
+++ b/trace-viewer/trace_viewer/base/ui/drag_handle.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   /**
    * Detects when user clicks handle determines new height of container based
@@ -19,7 +19,7 @@
    * @extends {HTMLDivElement}
    * You will need to set target to be the draggable element
    */
-  var DragHandle = tv.b.ui.define('x-drag-handle');
+  var DragHandle = tr.b.ui.define('x-drag-handle');
 
   DragHandle.prototype = {
     __proto__: HTMLDivElement.prototype,
diff --git a/trace-viewer/trace_viewer/base/ui/drag_handle_test.html b/trace-viewer/trace_viewer/base/ui/drag_handle_test.html
index 4280773..720765b 100644
--- a/trace-viewer/trace_viewer/base/ui/drag_handle_test.html
+++ b/trace-viewer/trace_viewer/base/ui/drag_handle_test.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var createDragHandle = function() {
     var el = document.createElement('div');
     el.style.border = '1px solid black';
@@ -23,7 +23,7 @@
     var lowerEl = document.createElement('div');
     lowerEl.style.height = '100px';
 
-    var dragHandle = new tv.b.ui.DragHandle();
+    var dragHandle = new tr.b.ui.DragHandle();
     dragHandle.target = lowerEl;
 
     el.appendChild(upperEl);
diff --git a/trace-viewer/trace_viewer/base/ui/dropdown.html b/trace-viewer/trace_viewer/base/ui/dropdown.html
index 8b72679..690839a 100644
--- a/trace-viewer/trace_viewer/base/ui/dropdown.html
+++ b/trace-viewer/trace_viewer/base/ui/dropdown.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/base/base.html">
 
-<polymer-element name="tv-b-dropdown">
+<polymer-element name="tr-b-ui-dropdown">
   <template>
     <style>
     :host {
diff --git a/trace-viewer/trace_viewer/base/ui/dropdown_test.html b/trace-viewer/trace_viewer/base/ui/dropdown_test.html
index 99cc4e4..d2bf24c 100644
--- a/trace-viewer/trace_viewer/base/ui/dropdown_test.html
+++ b/trace-viewer/trace_viewer/base/ui/dropdown_test.html
@@ -11,23 +11,23 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var dd = document.createElement('tv-b-dropdown');
+    var dd = document.createElement('tr-b-ui-dropdown');
     dd.style.marginLeft = '50px';
     dd.style.width = '50px';
     dd.iconElement.textContent = 'Settings ' + String.fromCharCode(0x2699);
 
-    dd.appendChild(tv.b.ui.createDiv({textContent: 'item 1'}));
-    dd.appendChild(tv.b.ui.createDiv({textContent: 'item 2 longer'}));
-    dd.appendChild(tv.b.ui.createDiv({textContent: 'item 3'}));
+    dd.appendChild(tr.b.ui.createDiv({textContent: 'item 1'}));
+    dd.appendChild(tr.b.ui.createDiv({textContent: 'item 2 longer'}));
+    dd.appendChild(tr.b.ui.createDiv({textContent: 'item 3'}));
 
-    var container = tv.b.ui.createDiv();
+    var container = tr.b.ui.createDiv();
     container.style.height = '100px';
     container.appendChild(dd);
-    container.appendChild(tv.b.ui.createDiv({textContent: 'some text'}));
-    container.appendChild(tv.b.ui.createDiv({textContent: 'some more text'}));
-    container.appendChild(tv.b.ui.createDiv({textContent: 'more text'}));
+    container.appendChild(tr.b.ui.createDiv({textContent: 'some text'}));
+    container.appendChild(tr.b.ui.createDiv({textContent: 'some more text'}));
+    container.appendChild(tr.b.ui.createDiv({textContent: 'more text'}));
     this.addHTMLOutput(container);
 
     dd.show();
diff --git a/trace-viewer/trace_viewer/base/ui/info_bar.html b/trace-viewer/trace_viewer/base/ui/info_bar.html
index 0925673..491f0b2 100644
--- a/trace-viewer/trace_viewer/base/ui/info_bar.html
+++ b/trace-viewer/trace_viewer/base/ui/info_bar.html
@@ -7,7 +7,7 @@
 <link rel="import" href="/base/ui.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
 
-<polymer-element name='tv-b-ui-info-bar' is='HTMLDivElement'>
+<polymer-element name='tr-b-ui-info-bar' is='HTMLDivElement'>
   <template>
     <style>
     :host {
diff --git a/trace-viewer/trace_viewer/base/ui/info_bar_group.html b/trace-viewer/trace_viewer/base/ui/info_bar_group.html
index fb34cfb..c3dffe6 100644
--- a/trace-viewer/trace_viewer/base/ui/info_bar_group.html
+++ b/trace-viewer/trace_viewer/base/ui/info_bar_group.html
@@ -6,7 +6,7 @@
 -->
 <link rel='import' href='/base/ui/info_bar.html'>
 
-<polymer-element name='tv-b-ui-info-bar-group' is='HTMLUnknownElement'>
+<polymer-element name='tr-b-ui-info-bar-group' is='HTMLUnknownElement'>
   <template>
     <style>
     :host {
@@ -49,7 +49,7 @@
     updateContents_: function() {
       this.$.messages.textContent = '';
       this.messages_.forEach(function(message) {
-        var bar = document.createElement('tv-b-ui-info-bar');
+        var bar = document.createElement('tr-b-ui-info-bar');
         bar.message = message.text;
         bar.visible = true;
 
diff --git a/trace-viewer/trace_viewer/base/ui/info_bar_group_test.html b/trace-viewer/trace_viewer/base/ui/info_bar_group_test.html
index 4b1719e..999ba06 100644
--- a/trace-viewer/trace_viewer/base/ui/info_bar_group_test.html
+++ b/trace-viewer/trace_viewer/base/ui/info_bar_group_test.html
@@ -9,9 +9,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('group-instantiate', function() {
-    var infoBarGroup = document.createElement('tv-b-ui-info-bar-group');
+    var infoBarGroup = document.createElement('tr-b-ui-info-bar-group');
     infoBarGroup.addMessage(
         'Message 1',
         [{buttonText: 'ok', onClick: function() {}}]);
@@ -22,7 +22,7 @@
   });
 
   test('group-populate-then-clear', function() {
-    var infoBarGroup = document.createElement('tv-b-ui-info-bar-group');
+    var infoBarGroup = document.createElement('tr-b-ui-info-bar-group');
     infoBarGroup.addMessage(
         'Message 1',
         [{buttonText: 'ok', onClick: function() {}}]);
@@ -34,7 +34,7 @@
   });
 
   test('group-populate-clear-repopulate', function() {
-    var infoBarGroup = document.createElement('tv-b-ui-info-bar-group');
+    var infoBarGroup = document.createElement('tr-b-ui-info-bar-group');
     infoBarGroup.addMessage(
         'Message 1',
         [{buttonText: 'ok', onClick: function() {}}]);
diff --git a/trace-viewer/trace_viewer/base/ui/info_bar_test.html b/trace-viewer/trace_viewer/base/ui/info_bar_test.html
index 84e73cc..325f4a6 100644
--- a/trace-viewer/trace_viewer/base/ui/info_bar_test.html
+++ b/trace-viewer/trace_viewer/base/ui/info_bar_test.html
@@ -8,16 +8,16 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
-    var infoBar = document.createElement('tv-b-ui-info-bar');
+    var infoBar = document.createElement('tr-b-ui-info-bar');
     infoBar.message = 'This is an info';
     infoBar.visible = true;
     this.addHTMLOutput(infoBar);
   });
 
   test('buttons', function() {
-    var infoBar = document.createElement('tv-b-ui-info-bar');
+    var infoBar = document.createElement('tr-b-ui-info-bar');
     infoBar.visible = true;
     infoBar.message = 'This is an info bar with buttons';
     var didClick = false;
@@ -30,7 +30,7 @@
   });
 
   test('hiding', function() {
-    var infoBar = document.createElement('tv-b-ui-info-bar');
+    var infoBar = document.createElement('tr-b-ui-info-bar');
     infoBar.message = 'This is an info bar';
     infoBar.visible = true;
     this.addHTMLOutput(infoBar);
diff --git a/trace-viewer/trace_viewer/base/ui/line_chart.html b/trace-viewer/trace_viewer/base/ui/line_chart.html
index 4297ab2..c44d032 100644
--- a/trace-viewer/trace_viewer/base/ui/line_chart.html
+++ b/trace-viewer/trace_viewer/base/ui/line_chart.html
@@ -12,9 +12,9 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
-  var ChartBase = tv.b.ui.ChartBase;
-  var getColorOfKey = tv.b.ui.getColorOfKey;
+tr.exportTo('tr.b.ui', function() {
+  var ChartBase = tr.b.ui.ChartBase;
+  var getColorOfKey = tr.b.ui.getColorOfKey;
 
   function getSampleWidth(data, index, leftSide) {
     var leftIndex, rightIndex;
@@ -33,7 +33,7 @@
   /**
    * @constructor
    */
-  var LineChart = tv.b.ui.define('line-chart', ChartBase);
+  var LineChart = tr.b.ui.define('line-chart', ChartBase);
 
   LineChart.prototype = {
     __proto__: ChartBase.prototype,
@@ -42,7 +42,7 @@
       ChartBase.prototype.decorate.call(this);
       this.classList.add('line-chart');
 
-      this.brushedRange_ = new tv.b.Range();
+      this.brushedRange_ = new tr.b.Range();
 
       this.xScale_ = d3.scale.linear();
       this.yScale_ = d3.scale.linear();
@@ -94,7 +94,7 @@
     },
 
     computeBrushRangeFromIndices: function(indexA, indexB) {
-      var r = new tv.b.Range();
+      var r = new tr.b.Range();
       var leftIndex = Math.min(indexA, indexB);
       var rightIndex = Math.max(indexA, indexB);
       leftIndex = Math.max(0, leftIndex);
@@ -122,7 +122,7 @@
       this.xScale_.domain(d3.extent(this.data_, function(d) { return d.x; }));
 
       // Y.
-      var yRange = new tv.b.Range();
+      var yRange = new tr.b.Range();
       this.data_.forEach(function(d) {
         this.seriesKeys_.forEach(function(k) {
           yRange.addValue(d[k]);
@@ -206,7 +206,7 @@
       var index = this.getDataIndexAtClientPoint_(e.clientX, e.clientY, true);
 
       if (index !== undefined) {
-        tv.b.ui.trackMouseMovesUntilMouseUp(
+        tr.b.ui.trackMouseMovesUntilMouseUp(
             this.onMouseMove_.bind(this, e.button),
             this.onMouseUp_.bind(this, e.button));
       }
diff --git a/trace-viewer/trace_viewer/base/ui/line_chart_test.html b/trace-viewer/trace_viewer/base/ui/line_chart_test.html
index cae753b..0a3554d 100644
--- a/trace-viewer/trace_viewer/base/ui/line_chart_test.html
+++ b/trace-viewer/trace_viewer/base/ui/line_chart_test.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('singleSeries', function() {
-    var chart = new tv.b.ui.LineChart();
+    var chart = new tr.b.ui.LineChart();
     chart.width = 400;
     chart.height = 200;
     chart.chartTitle = 'Chart title';
@@ -25,7 +25,7 @@
   });
 
   test('twoSeries', function() {
-    var chart = new tv.b.ui.LineChart();
+    var chart = new tr.b.ui.LineChart();
 
     chart.width = 400;
     chart.height = 200;
@@ -38,7 +38,7 @@
     ];
     chart.data = data;
 
-    var r = new tv.b.Range();
+    var r = new tr.b.Range();
     r.addValue(20);
     r.addValue(40);
     chart.brushedRange = r;
@@ -47,7 +47,7 @@
   });
 
   test('brushRangeFromIndices', function() {
-    var chart = new tv.b.ui.LineChart();
+    var chart = new tr.b.ui.LineChart();
     var data = [
       {x: 10, value: 50},
       {x: 30, value: 60},
@@ -56,7 +56,7 @@
       {x: 120, value: 90}
     ];
     chart.data = data;
-    var r = new tv.b.Range();
+    var r = new tr.b.Range();
 
     // Range min should be 10.
     r = chart.computeBrushRangeFromIndices(-2, 1);
@@ -78,7 +78,7 @@
   });
 
   test('interactiveBrushing', function() {
-    var chart = new tv.b.ui.LineChart();
+    var chart = new tr.b.ui.LineChart();
     chart.width = 400;
     chart.height = 200;
     chart.chartTitle = 'Chart title';
@@ -99,7 +99,7 @@
 
     function updateBrushedRange() {
       if (mouseDownIndex === undefined) {
-        chart.brushedRange = new tv.b.Range();
+        chart.brushedRange = new tr.b.Range();
         return;
       }
       chart.brushedRange = chart.computeBrushRangeFromIndices(
diff --git a/trace-viewer/trace_viewer/base/ui/list_and_associated_view.html b/trace-viewer/trace_viewer/base/ui/list_and_associated_view.html
index bae7d0d..e568e0c 100644
--- a/trace-viewer/trace_viewer/base/ui/list_and_associated_view.html
+++ b/trace-viewer/trace_viewer/base/ui/list_and_associated_view.html
@@ -14,12 +14,12 @@
  * @fileoverview A list of things, and a viewer for the currently selected
  * thing.
  */
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   /**
    * @constructor
    */
-  var ListAndAssociatedView = tv.b.ui.define('x-list-and-associated-view');
+  var ListAndAssociatedView = tr.b.ui.define('x-list-and-associated-view');
   ListAndAssociatedView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
 
@@ -28,7 +28,7 @@
       this.listProperty_ = undefined;
       this.view_ = undefined;
       this.viewProperty_ = undefined;
-      this.listView_ = new tv.b.ui.ListView();
+      this.listView_ = new tr.b.ui.ListView();
       this.listView_.addEventListener('selection-changed',
                                       this.onSelectionChanged_.bind(this));
       this.placeholder_ = document.createElement('div');
diff --git a/trace-viewer/trace_viewer/base/ui/list_and_associated_view_test.html b/trace-viewer/trace_viewer/base/ui/list_and_associated_view_test.html
index be96f02..83c5fdb 100644
--- a/trace-viewer/trace_viewer/base/ui/list_and_associated_view_test.html
+++ b/trace-viewer/trace_viewer/base/ui/list_and_associated_view_test.html
@@ -8,10 +8,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ListAndAssociatedView = tv.b.ui.ListAndAssociatedView;
+tr.b.unittest.testSuite(function() {
+  var ListAndAssociatedView = tr.b.ui.ListAndAssociatedView;
 
-  var SimpleView = tv.b.ui.define('div');
+  var SimpleView = tr.b.ui.define('div');
   SimpleView.prototype = {
     __proto__: HTMLDivElement.prototype,
 
diff --git a/trace-viewer/trace_viewer/base/ui/list_view.html b/trace-viewer/trace_viewer/base/ui/list_view.html
index 738d11e..14370b7 100644
--- a/trace-viewer/trace_viewer/base/ui/list_view.html
+++ b/trace-viewer/trace_viewer/base/ui/list_view.html
@@ -15,18 +15,18 @@
 /**
  * @fileoverview Simple list view.
  */
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   /**
    * @constructor
    */
-  var ListView = tv.b.ui.define(
-      'x-list-view', tv.b.ui.ContainerThatDecoratesItsChildren);
+  var ListView = tr.b.ui.define(
+      'x-list-view', tr.b.ui.ContainerThatDecoratesItsChildren);
 
   ListView.prototype = {
-    __proto__: tv.b.ui.ContainerThatDecoratesItsChildren.prototype,
+    __proto__: tr.b.ui.ContainerThatDecoratesItsChildren.prototype,
 
     decorate: function() {
-      tv.b.ui.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);
+      tr.b.ui.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);
 
       this.classList.add('x-list-view');
       this.onItemClicked_ = this.onItemClicked_.bind(this);
@@ -56,7 +56,7 @@
                 this.removeAttribute('selected');
               var newSelection = listView.selectedElement;
               if (newSelection != oldSelection)
-                tv.b.dispatchSimpleEvent(listView, 'selection-changed', false);
+                tr.b.dispatchSimpleEvent(listView, 'selection-changed', false);
             },
             get: function() {
               return this.hasAttribute('selected');
@@ -78,7 +78,7 @@
 
     doneDecoratingForNow_: function() {
       if (this.selectionChanged_)
-        tv.b.dispatchSimpleEvent(this, 'selection-changed', false);
+        tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
     },
 
     get selectedElement() {
@@ -107,9 +107,9 @@
 
     clear: function() {
       var changed = this.selectedElement !== undefined;
-      tv.b.ui.ContainerThatDecoratesItsChildren.prototype.clear.call(this);
+      tr.b.ui.ContainerThatDecoratesItsChildren.prototype.clear.call(this);
       if (changed)
-        tv.b.dispatchSimpleEvent(this, 'selection-changed', false);
+        tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
     },
 
     onItemClicked_: function(e) {
@@ -121,7 +121,7 @@
         element = element.parentElement;
       if (element !== currentSelectedElement)
         element.setAttribute('selected', 'selected');
-      tv.b.dispatchSimpleEvent(this, 'selection-changed', false);
+      tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
     },
 
     onKeyDown_: function(e) {
@@ -132,7 +132,7 @@
         var prev = this.selectedElement.previousSibling;
         if (prev) {
           prev.selected = true;
-          tv.b.scrollIntoViewIfNeeded(prev);
+          tr.b.scrollIntoViewIfNeeded(prev);
           e.preventDefault();
           return true;
         }
@@ -140,7 +140,7 @@
         var next = this.selectedElement.nextSibling;
         if (next) {
           next.selected = true;
-          tv.b.scrollIntoViewIfNeeded(next);
+          tr.b.scrollIntoViewIfNeeded(next);
           e.preventDefault();
           return true;
         }
diff --git a/trace-viewer/trace_viewer/base/ui/list_view_test.html b/trace-viewer/trace_viewer/base/ui/list_view_test.html
index 3978ad7..6cebe56 100644
--- a/trace-viewer/trace_viewer/base/ui/list_view_test.html
+++ b/trace-viewer/trace_viewer/base/ui/list_view_test.html
@@ -8,8 +8,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ListView = tv.b.ui.ListView;
+tr.b.unittest.testSuite(function() {
+  var ListView = tr.b.ui.ListView;
 
   test('instantiate', function() {
     var view = new ListView();
diff --git a/trace-viewer/trace_viewer/base/ui/mouse_mode_selector.html b/trace-viewer/trace_viewer/base/ui/mouse_mode_selector.html
index 03b3b5f..4dd7c61 100644
--- a/trace-viewer/trace_viewer/base/ui/mouse_mode_selector.html
+++ b/trace-viewer/trace_viewer/base/ui/mouse_mode_selector.html
@@ -24,7 +24,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   var THIS_DOC = document.currentScript.ownerDocument;
 
@@ -110,7 +110,7 @@
    * @constructor
    * @extends {HTMLDivElement}
    */
-  var MouseModeSelector = tv.b.ui.define('div');
+  var MouseModeSelector = tr.b.ui.define('div');
 
   MouseModeSelector.prototype = {
     __proto__: HTMLDivElement.prototype,
@@ -118,7 +118,7 @@
     decorate: function(opt_targetElement) {
       this.classList.add('mouse-mode-selector');
 
-      var node = tv.b.instantiateTemplate('#mouse-mode-selector-template',
+      var node = tr.b.instantiateTemplate('#mouse-mode-selector-template',
                                           THIS_DOC);
       this.appendChild(node);
 
@@ -145,9 +145,9 @@
       this.buttonsEl_.addEventListener('mousedown', this.onButtonMouseDown_);
       this.buttonsEl_.addEventListener('click', this.onButtonPress_.bind(this));
 
-      tv.b.KeyEventManager.instance.addListener(
+      tr.b.KeyEventManager.instance.addListener(
           'keydown', this.onKeyDown_, this);
-      tv.b.KeyEventManager.instance.addListener(
+      tr.b.KeyEventManager.instance.addListener(
           'keyup', this.onKeyUp_, this);
       this.keyCodeCondition = undefined;
 
@@ -192,7 +192,7 @@
       if (!this.settingsKey_)
         return;
 
-      var mode = tv.b.Settings.get(this.settingsKey_ + '.mode', undefined);
+      var mode = tr.b.Settings.get(this.settingsKey_ + '.mode', undefined);
       // Modes changed from 1,2,3,4 to 0x1, 0x2, 0x4, 0x8. Fix any stray
       // settings to the best of our abilities.
       if (allModeInfo[mode] === undefined)
@@ -207,7 +207,7 @@
         mode = this.defaultMode_;
       this.mode = mode;
 
-      var pos = tv.b.Settings.get(this.settingsKey_ + '.pos', undefined);
+      var pos = tr.b.Settings.get(this.settingsKey_ + '.pos', undefined);
       if (pos)
         this.pos = pos;
     },
@@ -279,7 +279,7 @@
         }
 
         // Exit event.
-        tv.b.dispatchSimpleEvent(this, modeInfo.eventNames.exit, true);
+        tr.b.dispatchSimpleEvent(this, modeInfo.eventNames.exit, true);
       }
 
       this.currentMode_ = newMode;
@@ -296,7 +296,7 @@
 
         // Enter event.
         if (!this.isInAlternativeMode_)
-          tv.b.dispatchSimpleEvent(this, modeInfo.eventNames.enter, true);
+          tr.b.dispatchSimpleEvent(this, modeInfo.eventNames.enter, true);
 
         // Begin event.
         if (this.isInteracting_) {
@@ -309,7 +309,7 @@
       }
 
       if (this.settingsKey_ && !this.isInAlternativeMode_)
-        tv.b.Settings.set(this.settingsKey_ + '.mode', this.mode);
+        tr.b.Settings.set(this.settingsKey_ + '.mode', this.mode);
     },
 
     setKeyCodeForMode: function(mode, keyCode) {
@@ -338,7 +338,7 @@
     },
 
     createEvent_: function(eventName, sourceEvent) {
-      var event = new tv.b.Event(eventName, true);
+      var event = new tr.b.Event(eventName, true);
       event.clientX = this.mousePos_.x;
       event.clientY = this.mousePos_.y;
       event.deltaX = this.mousePos_.x - this.mouseDownPos_.x;
@@ -369,7 +369,7 @@
       this.dispatchEvent(mouseEvent);
       this.isInteracting_ = true;
       this.isClick_ = true;
-      tv.b.ui.trackMouseMovesUntilMouseUp(this.onMouseMove_, this.onMouseUp_);
+      tr.b.ui.trackMouseMovesUntilMouseUp(this.onMouseMove_, this.onMouseUp_);
     },
 
     onMouseMove_: function(e) {
@@ -432,7 +432,7 @@
       }
 
       var didHandleKey = false;
-      tv.b.iterItems(this.modeToKeyCodeMap_, function(modeStr, keyCode) {
+      tr.b.iterItems(this.modeToKeyCodeMap_, function(modeStr, keyCode) {
         if (e.keyCode === keyCode) {
           this.modeBeforeAlternativeModeActivated_ = undefined;
           var mode = parseInt(modeStr);
@@ -453,7 +453,7 @@
       var shiftPressed = e.shiftKey;
       var spacePressed = this.spacePressed_;
       var cmdOrCtrlPressed =
-          (tv.isMac && e.metaKey) || (!tv.isMac && e.ctrlKey);
+          (tr.isMac && e.metaKey) || (!tr.isMac && e.ctrlKey);
 
       // Figure out the new mode
       var smm = this.supportedModeMask_;
@@ -513,12 +513,12 @@
       this.style.top = pos.y + 'px';
 
       if (this.settingsKey_)
-        tv.b.Settings.set(this.settingsKey_ + '.pos', this.pos);
+        tr.b.Settings.set(this.settingsKey_ + '.pos', this.pos);
     },
 
     constrainPositionToBounds_: function(pos) {
       var parent = this.offsetParent || document.body;
-      var parentRect = tv.b.windowRectForElement(parent);
+      var parentRect = tr.b.windowRectForElement(parent);
 
       var top = 0;
       var bottom = parentRect.height - this.offsetHeight;
@@ -542,7 +542,7 @@
         x: e.clientX - this.offsetLeft,
         y: e.clientY - this.offsetTop
       };
-      tv.b.ui.trackMouseMovesUntilMouseUp(function(e) {
+      tr.b.ui.trackMouseMovesUntilMouseUp(function(e) {
         var pos = {};
         pos.x = e.clientX - mouseDownPos.x;
         pos.y = e.clientY - mouseDownPos.y;
diff --git a/trace-viewer/trace_viewer/base/ui/mouse_mode_selector_test.html b/trace-viewer/trace_viewer/base/ui/mouse_mode_selector_test.html
index f54332d..5193aab 100644
--- a/trace-viewer/trace_viewer/base/ui/mouse_mode_selector_test.html
+++ b/trace-viewer/trace_viewer/base/ui/mouse_mode_selector_test.html
@@ -8,10 +8,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var MOUSE_SELECTOR_MODE = tv.b.ui.MOUSE_SELECTOR_MODE;
+tr.b.unittest.testSuite(function() {
+  var MOUSE_SELECTOR_MODE = tr.b.ui.MOUSE_SELECTOR_MODE;
   test('instantiate', function() {
-    var sel = new tv.b.ui.MouseModeSelector();
+    var sel = new tr.b.ui.MouseModeSelector();
     sel.supportedModeMask =
         MOUSE_SELECTOR_MODE.SELECTION |
         MOUSE_SELECTOR_MODE.PANSCAN;
@@ -19,7 +19,7 @@
   });
 
   test('changeMaskWithUnsupportedMode', function() {
-    var sel = new tv.b.ui.MouseModeSelector();
+    var sel = new tr.b.ui.MouseModeSelector();
     sel.mode = MOUSE_SELECTOR_MODE.SELECTION;
     assert.throw(function() {
       sel.supportedModeMask = MOUSE_SELECTOR_MODE.ZOOM;
@@ -27,14 +27,14 @@
   });
 
   test('modePersists', function() {
-    var sel1 = new tv.b.ui.MouseModeSelector();
+    var sel1 = new tr.b.ui.MouseModeSelector();
     sel1.defaultMode_ = MOUSE_SELECTOR_MODE.ZOOM;
     sel1.settingsKey = 'foo';
     assert.equal(sel1.mode, MOUSE_SELECTOR_MODE.ZOOM);
 
     sel1.mode = MOUSE_SELECTOR_MODE.PANSCAN;
 
-    var sel2 = new tv.b.ui.MouseModeSelector();
+    var sel2 = new tr.b.ui.MouseModeSelector();
     sel2.settingsKey = 'foo';
     assert.equal(sel2.mode, MOUSE_SELECTOR_MODE.PANSCAN);
   });
diff --git a/trace-viewer/trace_viewer/base/ui/mouse_tracker.html b/trace-viewer/trace_viewer/base/ui/mouse_tracker.html
index 8d84e38..fa0d832 100644
--- a/trace-viewer/trace_viewer/base/ui/mouse_tracker.html
+++ b/trace-viewer/trace_viewer/base/ui/mouse_tracker.html
@@ -18,7 +18,7 @@
  *      'mouse-tracker-end' : mouseup and not tracking.
  */
 
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
 
   /**
    * @constructor
@@ -78,7 +78,7 @@
     },
 
     remakeEvent_: function(e, newType) {
-      var remade = new tv.b.Event(newType, true, true);
+      var remade = new tr.b.Event(newType, true, true);
       remade.x = e.x;
       remade.y = e.y;
       remade.offsetX = e.offsetX;
diff --git a/trace-viewer/trace_viewer/base/ui/overlay.html b/trace-viewer/trace_viewer/base/ui/overlay.html
index 197664e..350c91b 100644
--- a/trace-viewer/trace_viewer/base/ui/overlay.html
+++ b/trace-viewer/trace_viewer/base/ui/overlay.html
@@ -122,7 +122,7 @@
  * restores its original parentage.
  *
  */
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
   /**
@@ -130,7 +130,7 @@
    * @constructor
    * @extends {HTMLDivElement}
    */
-  var Overlay = tv.b.ui.define('overlay');
+  var Overlay = tr.b.ui.define('overlay');
 
   Overlay.prototype = {
     __proto__: HTMLDivElement.prototype,
@@ -153,13 +153,13 @@
       this.onClose_ = this.onClose_.bind(this);
 
       this.addEventListener('visibleChange',
-          tv.b.ui.Overlay.prototype.onVisibleChange_.bind(this), true);
+          tr.b.ui.Overlay.prototype.onVisibleChange_.bind(this), true);
 
       // Setup the shadow root
       var createShadowRoot = this.createShadowRoot ||
           this.webkitCreateShadowRoot;
       this.shadow_ = createShadowRoot.call(this);
-      this.shadow_.appendChild(tv.b.instantiateTemplate('#overlay-template',
+      this.shadow_.appendChild(tr.b.instantiateTemplate('#overlay-template',
                                                         THIS_DOC));
 
       this.closeBtn_ = this.shadow_.querySelector('close-button');
@@ -205,7 +205,7 @@
       if (this.visible_ === newValue)
         return;
 
-      tv.b.setPropertyAndDispatchChange(this, 'visible', newValue);
+      tr.b.setPropertyAndDispatchChange(this, 'visible', newValue);
     },
 
     onVisibleChange_: function() {
@@ -258,7 +258,7 @@
           (e.type === 'keydown' && e.keyCode === 27))
         e.stopPropagation();
       e.preventDefault();
-      tv.b.dispatchSimpleEvent(this, 'closeclick');
+      tr.b.dispatchSimpleEvent(this, 'closeclick');
     },
 
     onFocusIn_: function(e) {
@@ -310,7 +310,7 @@
     o.title = 'Error';
     o.textContent = msg;
     if (opt_err) {
-      var e = tv.b.normalizeException(opt_err);
+      var e = tr.b.normalizeException(opt_err);
 
       var stackDiv = document.createElement('pre');
       stackDiv.textContent = e.stack;
diff --git a/trace-viewer/trace_viewer/base/ui/overlay_test.html b/trace-viewer/trace_viewer/base/ui/overlay_test.html
index 4065d78..2f1b7da 100644
--- a/trace-viewer/trace_viewer/base/ui/overlay_test.html
+++ b/trace-viewer/trace_viewer/base/ui/overlay_test.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function addShowButtonForDialog(dlg) {
     var btn = document.createElement('button');
     btn.textContent = 'Launch Overlay';
@@ -36,19 +36,19 @@
   }
 
   test('instantiate', function() {
-    var dlg = new tv.b.ui.Overlay();
+    var dlg = new tr.b.ui.Overlay();
     dlg.classList.add('example-overlay');
     dlg.title = 'ExampleOverlay';
     dlg.innerHTML = 'hello';
     dlg.buttons.appendChild(makeButton('i am a button'));
     dlg.buttons.appendChild(makeCloseButton(dlg));
-    dlg.buttons.appendChild(tv.b.ui.createSpan(
+    dlg.buttons.appendChild(tr.b.ui.createSpan(
         {textContent: 'i am a span'}));
     addShowButtonForDialog.call(this, dlg);
   });
 
   test('instantiate_noButtons', function() {
-    var dlg = new tv.b.ui.Overlay();
+    var dlg = new tr.b.ui.Overlay();
     dlg.classList.add('example-overlay');
     dlg.title = 'ExampleOverlay';
     dlg.innerHTML = 'hello';
@@ -56,7 +56,7 @@
   });
 
   test('instantiate_disableUserClose', function() {
-    var dlg = new tv.b.ui.Overlay();
+    var dlg = new tr.b.ui.Overlay();
     dlg.classList.add('example-overlay');
     dlg.userCanClose = false;
     dlg.title = 'Unclosable';
@@ -66,7 +66,7 @@
   });
 
   test('instantiateTall', function() {
-    var dlg = new tv.b.ui.Overlay();
+    var dlg = new tr.b.ui.Overlay();
     dlg.title = 'TallContent';
     var contentEl = document.createElement('div');
     contentEl.style.overflowY = 'auto';
@@ -84,7 +84,7 @@
   });
 
   test('instantiateTallWithManyDirectChildren', function() {
-    var dlg = new tv.b.ui.Overlay();
+    var dlg = new tr.b.ui.Overlay();
     dlg.title = 'TallContent';
     for (var i = 0; i < 100; i++) {
       var el = document.createElement('div');
@@ -98,7 +98,7 @@
   });
 
   test('closeclickEvent', function() {
-    var dlg = new tv.b.ui.Overlay();
+    var dlg = new tr.b.ui.Overlay();
     dlg.title = 'Test closeclick event';
     var closeBtn = makeCloseButton(dlg);
     dlg.buttons.appendChild(closeBtn);
diff --git a/trace-viewer/trace_viewer/base/ui/pie_chart.html b/trace-viewer/trace_viewer/base/ui/pie_chart.html
index 261f174..b77e796 100644
--- a/trace-viewer/trace_viewer/base/ui/pie_chart.html
+++ b/trace-viewer/trace_viewer/base/ui/pie_chart.html
@@ -13,16 +13,16 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
-  var ChartBase = tv.b.ui.ChartBase;
-  var getColorOfKey = tv.b.ui.getColorOfKey;
+tr.exportTo('tr.b.ui', function() {
+  var ChartBase = tr.b.ui.ChartBase;
+  var getColorOfKey = tr.b.ui.getColorOfKey;
 
   var MIN_RADIUS = 100;
 
   /**
    * @constructor
    */
-  var PieChart = tv.b.ui.define('pie-chart', ChartBase);
+  var PieChart = tr.b.ui.define('pie-chart', ChartBase);
 
   PieChart.prototype = {
     __proto__: ChartBase.prototype,
diff --git a/trace-viewer/trace_viewer/base/ui/pie_chart_test.html b/trace-viewer/trace_viewer/base/ui/pie_chart_test.html
index a6ca228..9353b27 100644
--- a/trace-viewer/trace_viewer/base/ui/pie_chart_test.html
+++ b/trace-viewer/trace_viewer/base/ui/pie_chart_test.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('simple', function() {
-    var chart = new tv.b.ui.PieChart();
+    var chart = new tr.b.ui.PieChart();
     chart.width = 400;
     chart.height = 200;
     assert.equal(chart.getAttribute('width'), '400');
@@ -32,7 +32,7 @@
   });
 
   test('withValueText', function() {
-    var chart = new tv.b.ui.PieChart();
+    var chart = new tr.b.ui.PieChart();
     chart.width = 400;
     chart.height = 200;
     chart.chartTitle = 'Chart title';
@@ -46,7 +46,7 @@
   });
 
   test('clickEvent', function() {
-    var chart = new tv.b.ui.PieChart();
+    var chart = new tr.b.ui.PieChart();
     chart.width = 400;
     chart.height = 200;
     chart.chartTitle = 'Chart title';
@@ -64,12 +64,12 @@
     });
 
     var arc0 = chart.querySelectorAll('.paths > path')[1];
-    tv.b.dispatchSimpleEvent(arc0, 'click');
+    tr.b.dispatchSimpleEvent(arc0, 'click');
     assert.isTrue(didGetClick);
   });
 
   test('lotsOfValues', function() {
-    var chart = new tv.b.ui.PieChart();
+    var chart = new tr.b.ui.PieChart();
     chart.chartTitle = 'Chart title';
     var data = [
       {label: 'a', value: 100},
@@ -93,7 +93,7 @@
   });
 
   test('denseValues', function() {
-    var chart = new tv.b.ui.PieChart();
+    var chart = new tr.b.ui.PieChart();
     chart.chartTitle = 'Chart title';
     var data = [
       {
diff --git a/trace-viewer/trace_viewer/base/ui/quad_stack_view.html b/trace-viewer/trace_viewer/base/ui/quad_stack_view.html
index 09018c8..ea0c83d 100644
--- a/trace-viewer/trace_viewer/base/ui/quad_stack_view.html
+++ b/trace-viewer/trace_viewer/base/ui/quad_stack_view.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/base/bbox2.html">
-<link rel="import" href="/base/gl_matrix.html">
+<link rel="import" href="/base/math.html">
 <link rel="import" href="/base/quad.html">
 <link rel="import" href="/base/raf.html">
 <link rel="import" href="/base/rect.html">
@@ -71,7 +71,7 @@
  * @fileoverview QuadStackView controls the content and viewing angle a
  * QuadStack.
  */
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
   var constants = {};
@@ -250,7 +250,7 @@
       quadCanvas.width = quad.imageData.width;
       quadCanvas.height = quad.imageData.height;
       quadCanvas.getContext('2d').putImageData(quad.imageData, 0, 0);
-      var quadBBox = new tv.b.BBox2();
+      var quadBBox = new tr.b.BBox2();
       quadBBox.addQuad(quad);
       var iw = quadCanvas.width;
       var ih = quadCanvas.height;
@@ -364,7 +364,7 @@
   /**
    * @constructor
    */
-  var QuadStackView = tv.b.ui.define('quad-stack-view');
+  var QuadStackView = tr.b.ui.define('quad-stack-view');
 
   QuadStackView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -372,7 +372,7 @@
     decorate: function() {
       this.className = 'quad-stack-view';
 
-      var node = tv.b.instantiateTemplate('#quad-stack-view-template',
+      var node = tr.b.instantiateTemplate('#quad-stack-view-template',
                                           THIS_DOC);
       this.appendChild(node);
       this.updateHeaderVisibility_();
@@ -385,7 +385,7 @@
 
       var stackingDistanceSlider = this.querySelector(
           '#stacking-distance-slider');
-      stackingDistanceSlider.value = tv.b.Settings.get(
+      stackingDistanceSlider.value = tr.b.Settings.get(
           'quadStackView.stackingDistance', 45);
       stackingDistanceSlider.addEventListener(
           'change', this.onStackingDistanceChange_.bind(this));
@@ -394,13 +394,13 @@
 
       this.trackMouse_();
 
-      this.camera_ = new tv.b.ui.Camera(this.mouseModeSelector_);
+      this.camera_ = new tr.b.ui.Camera(this.mouseModeSelector_);
       this.camera_.addEventListener('renderrequired',
           this.onRenderRequired_.bind(this));
       this.cameraWasReset_ = false;
       this.camera_.canvas = this.canvas_;
 
-      this.viewportRect_ = tv.b.Rect.fromXYWH(0, 0, 0, 0);
+      this.viewportRect_ = tr.b.Rect.fromXYWH(0, 0, 0, 0);
 
       this.pixelRatio_ = window.devicePixelRatio || 1;
     },
@@ -422,7 +422,7 @@
     },
 
     onStackingDistanceChange_: function(e) {
-      tv.b.Settings.set('quadStackView.stackingDistance',
+      tr.b.Settings.set('quadStackView.stackingDistance',
                         this.stackingDistance);
       this.scheduleRender();
       e.stopPropagation();
@@ -460,7 +460,7 @@
 
       var width = parseInt(window.getComputedStyle(this.offsetParent).width);
       var height = parseInt(window.getComputedStyle(this.offsetParent).height);
-      var rect = tv.b.Rect.fromXYWH(0, 0, width, height);
+      var rect = tr.b.Rect.fromXYWH(0, 0, width, height);
 
       if (rect.equalTo(this.viewportRect_))
         return false;
@@ -539,12 +539,12 @@
           this.chromeImages_.right, leftWidth + s * midWidth, 0);
 
       // Construct the quad.
-      var chromeRect = tv.b.Rect.fromXYWH(
+      var chromeRect = tr.b.Rect.fromXYWH(
           this.deviceRect_.x,
           this.deviceRect_.y - offsetY,
           this.deviceRect_.width,
           this.deviceRect_.height + offsetY);
-      var chromeQuad = tv.b.Quad.fromRect(chromeRect);
+      var chromeQuad = tr.b.Quad.fromRect(chromeRect);
       chromeQuad.stackingGroupId = this.maxStackingGroupId_ + 1;
       chromeQuad.imageData = chromeCtx.getImageData(
           0, 0, chromeCanvas.width, chromeCanvas.height);
@@ -559,7 +559,7 @@
       if (this.redrawScheduled_)
         return false;
       this.redrawScheduled_ = true;
-      tv.b.requestAnimationFrame(this.render, this);
+      tr.b.requestAnimationFrame(this.render, this);
     },
 
     onRenderRequired_: function(e) {
@@ -571,7 +571,7 @@
       var mv = this.camera_.modelViewMatrix;
       var p = this.camera_.projectionMatrix;
 
-      var viewport = tv.b.Rect.fromXYWH(
+      var viewport = tr.b.Rect.fromXYWH(
           0, 0, this.canvas_.width, this.canvas_.height);
 
       // Calculate the quad stacks.
@@ -632,24 +632,24 @@
     },
 
     trackMouse_: function() {
-      this.mouseModeSelector_ = new tv.b.ui.MouseModeSelector(this.canvas_);
+      this.mouseModeSelector_ = new tr.b.ui.MouseModeSelector(this.canvas_);
       this.mouseModeSelector_.supportedModeMask =
-          tv.b.ui.MOUSE_SELECTOR_MODE.SELECTION |
-          tv.b.ui.MOUSE_SELECTOR_MODE.PANSCAN |
-          tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM |
-          tv.b.ui.MOUSE_SELECTOR_MODE.ROTATE;
-      this.mouseModeSelector_.mode = tv.b.ui.MOUSE_SELECTOR_MODE.PANSCAN;
+          tr.b.ui.MOUSE_SELECTOR_MODE.SELECTION |
+          tr.b.ui.MOUSE_SELECTOR_MODE.PANSCAN |
+          tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM |
+          tr.b.ui.MOUSE_SELECTOR_MODE.ROTATE;
+      this.mouseModeSelector_.mode = tr.b.ui.MOUSE_SELECTOR_MODE.PANSCAN;
       this.mouseModeSelector_.pos = {x: 0, y: 100};
       this.appendChild(this.mouseModeSelector_);
       this.mouseModeSelector_.settingsKey =
           'quadStackView.mouseModeSelector';
 
       this.mouseModeSelector_.setModifierForAlternateMode(
-          tv.b.ui.MOUSE_SELECTOR_MODE.ROTATE, tv.b.ui.MODIFIER.SHIFT);
+          tr.b.ui.MOUSE_SELECTOR_MODE.ROTATE, tr.b.ui.MODIFIER.SHIFT);
       this.mouseModeSelector_.setModifierForAlternateMode(
-          tv.b.ui.MOUSE_SELECTOR_MODE.PANSCAN, tv.b.ui.MODIFIER.SPACE);
+          tr.b.ui.MOUSE_SELECTOR_MODE.PANSCAN, tr.b.ui.MODIFIER.SPACE);
       this.mouseModeSelector_.setModifierForAlternateMode(
-          tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM, tv.b.ui.MODIFIER.CMD_OR_CTRL);
+          tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM, tr.b.ui.MODIFIER.CMD_OR_CTRL);
 
       this.mouseModeSelector_.addEventListener('updateselection',
           this.onSelectionUpdate_.bind(this));
@@ -669,11 +669,11 @@
       var mousePos = this.extractRelativeMousePosition_(e);
       var res = [];
       function handleQuad(passNumber, quad, p1, p2, p3, p4) {
-        if (tv.b.pointInImplicitQuad(mousePos, p1, p2, p3, p4))
+        if (tr.b.pointInImplicitQuad(mousePos, p1, p2, p3, p4))
           res.push(quad);
       }
       this.stackTransformAndProcessQuads_(1, handleQuad, false);
-      var e = new Event('selectionchange', false, false);
+      var e = new Event('selectionchange');
       e.quads = res;
       this.dispatchEvent(e);
     }
diff --git a/trace-viewer/trace_viewer/base/ui/sortable_table.html b/trace-viewer/trace_viewer/base/ui/sortable_table.html
index 41de2e3..3272f4b 100644
--- a/trace-viewer/trace_viewer/base/ui/sortable_table.html
+++ b/trace-viewer/trace_viewer/base/ui/sortable_table.html
@@ -12,11 +12,11 @@
 /**
  * @fileoverview A sortable table with history states.
  */
-tv.exportTo('tv.b.ui', function() {
+tr.exportTo('tr.b.ui', function() {
   /**
    * @constructor
    */
-  var SortableTable = tv.b.ui.define('sortable-table');
+  var SortableTable = tr.b.ui.define('sortable-table');
 
   var UNSORTED_ARROW = '&#x25BF';
   var SORT_ASCENDING_ARROW = '&#x25BE';
diff --git a/trace-viewer/trace_viewer/base/ui/sortable_table_test.html b/trace-viewer/trace_viewer/base/ui/sortable_table_test.html
index 736acdb..dc2277c 100644
--- a/trace-viewer/trace_viewer/base/ui/sortable_table_test.html
+++ b/trace-viewer/trace_viewer/base/ui/sortable_table_test.html
@@ -10,8 +10,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var SortableTable = tv.b.ui.SortableTable;
+tr.b.unittest.testSuite(function() {
+  var SortableTable = tr.b.ui.SortableTable;
 
   function convertToHTML(s) {
     var res = '';
diff --git a/trace-viewer/trace_viewer/base/ui/sunburst_chart.html b/trace-viewer/trace_viewer/base/ui/sunburst_chart.html
index 6a00e46..cf4fb77 100644
--- a/trace-viewer/trace_viewer/base/ui/sunburst_chart.html
+++ b/trace-viewer/trace_viewer/base/ui/sunburst_chart.html
@@ -12,16 +12,16 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.ui', function() {
-  var ChartBase = tv.b.ui.ChartBase;
-  var getColorOfKey = tv.b.ui.getColorOfKey;
+tr.exportTo('tr.b.ui', function() {
+  var ChartBase = tr.b.ui.ChartBase;
+  var getColorOfKey = tr.b.ui.getColorOfKey;
 
   var MIN_RADIUS = 100;
 
   /**
    * @constructor
    */
-  var SunburstChart = tv.b.ui.define('sunburst-chart', ChartBase);
+  var SunburstChart = tr.b.ui.define('sunburst-chart', ChartBase);
 
   SunburstChart.prototype = {
     __proto__: ChartBase.prototype,
@@ -100,7 +100,7 @@
     },
 
     getMinSize: function() {
-      if (!tv.b.ui.isElementAttachedToDocument(this))
+      if (!tr.b.ui.isElementAttachedToDocument(this))
         throw new Error('Cannot measure when unattached');
       this.updateContents_();
 
diff --git a/trace-viewer/trace_viewer/base/ui/sunburst_chart_test.html b/trace-viewer/trace_viewer/base/ui/sunburst_chart_test.html
index 8a8c41a..864c59d 100644
--- a/trace-viewer/trace_viewer/base/ui/sunburst_chart_test.html
+++ b/trace-viewer/trace_viewer/base/ui/sunburst_chart_test.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('simple', function() {
-    var chart = new tv.b.ui.SunburstChart();
+    var chart = new tr.b.ui.SunburstChart();
     chart.width = 600;
     chart.height = 600;
     assert.equal(chart.getAttribute('width'), '600');
diff --git a/trace-viewer/trace_viewer/core/analysis/table_builder.html b/trace-viewer/trace_viewer/base/ui/table.html
similarity index 94%
rename from trace-viewer/trace_viewer/core/analysis/table_builder.html
rename to trace-viewer/trace_viewer/base/ui/table.html
index 6466aa8..e3473c8 100644
--- a/trace-viewer/trace_viewer/core/analysis/table_builder.html
+++ b/trace-viewer/trace_viewer/base/ui/table.html
@@ -5,13 +5,12 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/analysis/toggle_container.html">
 <link rel="import" href="/base/utils.html">
 
 <!--
 @fileoverview A container that constructs a table-like container.
 -->
-<polymer-element name="tracing-analysis-nested-table">
+<polymer-element name="tr-b-ui-table">
   <template>
     <style>
       :host {
@@ -156,6 +155,7 @@
         this.headerCells_ = [];
         this.showHeader_ = true;
         this.emptyValue_ = undefined;
+        this.subRowsPropertyName_ = 'subRows';
       },
 
       ready: function() {
@@ -179,6 +179,7 @@
         this.sortDescending_ = false;
         this.columnsWithExpandButtons_ = [];
         this.headerCells_ = [];
+        this.subRowsPropertyName_ = 'subRows';
       },
 
       get showHeader() {
@@ -190,6 +191,10 @@
         this.scheduleRebuildHeaders_();
       },
 
+      set subRowsPropertyName(name) {
+        this.subRowsPropertyName_ = name;
+      },
+
       get emptyValue() {
         return this.emptyValue_;
       },
@@ -263,7 +268,8 @@
        * @param {Array} rows An array of 'row' objects with the following
        * fields:
        *   optional: subRows An array of objects that have the same 'row'
-       *                     structure.
+       *                     structure. Set subRowsPropertyName to use an
+       *                     alternative field name.
        */
       set tableRows(rows) {
         this.selectedTableRowInfo_ = undefined;
@@ -349,7 +355,7 @@
         // Sort expanded sub rows recursively.
         for (var i = 0; i < rows.length; i++) {
           if (rows[i].isExpanded)
-            this.sortRows_(rows[i].subRows);
+            this.sortRows_(rows[i][this.subRowsPropertyName_]);
         }
       },
 
@@ -363,7 +369,7 @@
         for (var i = 0; i < this.tableColumns_.length; i++) {
           var td = this.appendNewElement_(tr, 'td');
 
-          var headerCell = new TracingAnalysisHeaderCell();
+          var headerCell = document.createElement('tr-b-ui-table-header-cell');
 
           if (this.showHeader)
             headerCell.cellTitle = this.tableColumns_[i].title;
@@ -452,7 +458,6 @@
       generateTableRowNodes_: function(tableSection, userRows, rowInfoMap,
                                        indentation, lastAddedRow,
                                        parentRowInfo) {
-
         if (this.sortColumnIndex_ !== undefined &&
             tableSection === this.$.body) {
           userRows = userRows.slice(); // Don't mess with the input data.
@@ -488,7 +493,7 @@
 
           // Append subrows now.
           lastAddedRow = this.generateTableRowNodes_(
-              tableSection, userRow.subRows, rowInfoMap,
+              tableSection, userRow[this.subRowsPropertyName_], rowInfoMap,
               indentation + 1, lastAddedRow, rowInfo);
         }
         return lastAddedRow;
@@ -536,8 +541,8 @@
             td.classList.add('supports-selection');
 
           if (this.columnsWithExpandButtons_.indexOf(i) != -1) {
-            if (rowInfo.userRow.subRows &&
-                rowInfo.userRow.subRows.length > 0) {
+            if (rowInfo.userRow[this.subRowsPropertyName_] &&
+                rowInfo.userRow[this.subRowsPropertyName_].length > 0) {
               td.style.paddingLeft = INDENT_SPACE + 'px';
               var expandButton = this.appendNewElement_(td,
                   'expand-button');
@@ -592,7 +597,8 @@
                                       tdThatWasClicked.columnIndex);
               }
               if (isAlreadySelected) {
-                if (rowInfo.userRow.subRows && rowInfo.userRow.subRows.length) {
+                if (rowInfo.userRow[this.subRowsPropertyName_] &&
+                    rowInfo.userRow[this.subRowsPropertyName_].length) {
                   this.setExpandedForUserRow_(
                       tableSection, rowInfoMap,
                       rowInfo.userRow, !rowInfo.isExpanded);
@@ -602,7 +608,8 @@
                     rowInfo, tdThatWasClicked.columnIndex);
               }
             } else {
-              if (rowInfo.userRow.subRows && rowInfo.userRow.subRows.length) {
+              if (rowInfo.userRow[this.subRowsPropertyName_] &&
+                  rowInfo.userRow[this.subRowsPropertyName_].length) {
                 this.setExpandedForUserRow_(
                     tableSection, rowInfoMap,
                     rowInfo.userRow, !rowInfo.isExpanded);
@@ -615,10 +622,11 @@
       },
 
       removeSubNodes_: function(tableSection, rowInfo, rowInfoMap) {
-        if (rowInfo.userRow.subRows === undefined)
+        if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
           return;
-        for (var i = 0; i < rowInfo.userRow.subRows.length; i++) {
-          var subRow = rowInfo.userRow.subRows[i];
+        for (var i = 0;
+             i < rowInfo.userRow[this.subRowsPropertyName_].length; i++) {
+          var subRow = rowInfo.userRow[this.subRowsPropertyName_][i];
           var subRowInfo = rowInfoMap.get(subRow);
           if (!subRowInfo)
             continue;
@@ -752,10 +760,10 @@
         if (rowInfo.isExpanded) {
           expandButton.classList.add('button-expanded');
           var lastAddedRow = rowInfo.htmlNode;
-          if (rowInfo.userRow.subRows) {
+          if (rowInfo.userRow[this.subRowsPropertyName_]) {
             this.generateTableRowNodes_(
                 tableSection,
-                rowInfo.userRow.subRows, rowInfoMap,
+                rowInfo.userRow[this.subRowsPropertyName_], rowInfoMap,
                 rowInfo.indentation + 1,
                 lastAddedRow, rowInfo);
           }
@@ -915,7 +923,7 @@
       },
 
       prepareToChangeSelection_: function() {
-        var e = new Event('selection-changed', false, false);
+        var e = new Event('selection-changed');
         var previousSelectedRowInfo = this.selectedTableRowInfo_;
         if (previousSelectedRowInfo)
           e.previousSelectedTableRow = previousSelectedRowInfo.userRow;
@@ -1019,7 +1027,7 @@
         if (cmdName === 'ARROW_UP') {
           var prev = htmlNode.previousElementSibling;
           if (prev) {
-            tv.b.scrollIntoViewIfNeeded(prev);
+            tr.b.scrollIntoViewIfNeeded(prev);
             this.selectedTableRow = prev.rowInfo.userRow;
             this.focusSelected_();
             return;
@@ -1030,7 +1038,7 @@
         if (cmdName === 'ARROW_DOWN') {
           var next = htmlNode.nextElementSibling;
           if (next) {
-            tv.b.scrollIntoViewIfNeeded(next);
+            tr.b.scrollIntoViewIfNeeded(next);
             this.selectedTableRow = next.rowInfo.userRow;
             this.focusSelected_();
             return;
@@ -1050,14 +1058,15 @@
             return;
 
           } else {
-            if (rowInfo.userRow.subRows === undefined)
+            if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
               return;
-            if (rowInfo.userRow.subRows.length === 0)
+            if (rowInfo.userRow[this.subRowsPropertyName_].length === 0)
               return;
 
             if (!rowInfo.isExpanded)
               this.setExpandedForTableRow(rowInfo.userRow, true);
-            this.selectedTableRow = rowInfo.userRow.subRows[0];
+            this.selectedTableRow =
+              rowInfo.userRow[this.subRowsPropertyName_][0];
             this.focusSelected_();
             return;
           }
@@ -1105,9 +1114,7 @@
   })();
   </script>
 </polymer-element>
-<polymer-element name="tracing-analysis-header-cell"
-    constructor="TracingAnalysisHeaderCell"
-    on-tap="onTap_">
+<polymer-element name="tr-b-ui-table-header-cell" on-tap="onTap_">
   <template>
   <style>
     :host {
diff --git a/trace-viewer/trace_viewer/base/ui/table_header_cell.html b/trace-viewer/trace_viewer/base/ui/table_header_cell.html
new file mode 100644
index 0000000..7aa5854
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/ui/table_header_cell.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 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="import" href="/base/utils.html">
+
+<polymer-element name="tr-b-ui-table-header-cell"
+    on-tap="onTap_">
+  <template>
+  <style>
+    :host {
+      -webkit-user-select: none;
+      display: flex;
+    }
+
+    span {
+      flex: 0 1 auto;
+    }
+
+    side-element {
+      -webkit-user-select: none;
+      flex: 1 0 auto;
+      padding-left: 4px;
+      vertical-align: top;
+      font-size: 15px;
+      font-family: sans-serif;
+      display: inline;
+      line-height: 85%;
+    }
+  </style>
+
+    <span id="title"></span><side-element id="side"></side-element>
+  </template>
+
+  <script>
+  'use strict';
+
+  Polymer({
+    created: function() {
+      this.tapCallback_ = undefined;
+      this.cellTitle_ = '';
+    },
+
+    set cellTitle(value) {
+      this.cellTitle_ = value;
+
+      var titleNode;
+      if (this.cellTitle_ instanceof Node)
+        titleNode = this.cellTitle_;
+      else
+        titleNode = this.ownerDocument.createTextNode(this.cellTitle_);
+
+      this.$.title.innerText = '';
+      this.$.title.appendChild(titleNode);
+    },
+
+    get cellTitle() {
+      return this.cellTitle_;
+    },
+
+    clearSideContent: function() {
+      this.$.side.textContent = '';
+    },
+
+    set sideContent(content) {
+      this.$.side.textContent = content;
+    },
+
+    get sideContent() {
+      return this.$.side.textContent;
+    },
+
+    set tapCallback(callback) {
+      this.style.cursor = 'pointer';
+      this.tapCallback_ = callback;
+    },
+
+    get tapCallback() {
+      return this.tapCallback_;
+    },
+
+    onTap_: function() {
+      if (this.tapCallback_)
+        this.tapCallback_();
+    }
+  });
+</script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/table_builder_test.html b/trace-viewer/trace_viewer/base/ui/table_test.html
similarity index 89%
rename from trace-viewer/trace_viewer/core/analysis/table_builder_test.html
rename to trace-viewer/trace_viewer/base/ui/table_test.html
index 0d000c6..c9a2314 100644
--- a/trace-viewer/trace_viewer/core/analysis/table_builder_test.html
+++ b/trace-viewer/trace_viewer/base/ui/table_test.html
@@ -6,12 +6,12 @@
 -->
 
 <link rel="import" href="/base/deep_utils.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var THIS_DOC = document._currentScript.ownerDocument;
 
   test('instantiateEmptyTable_withoutEmptyValue', function() {
@@ -27,7 +27,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = [];
     table.rebuild();
@@ -39,6 +39,13 @@
     var firstColumnHeader = table.$.head.children[0].children[0];
     assert.closeTo(firstColumnHeader.offsetWidth, 300, 20);
 
+    // Check that the first column has a non-empty header.
+    var firstColumnTitle = tr.b.findDeepElementMatchingPredicate(
+        firstColumnHeader, function(element) {
+      return element.textContent === 'First Column';
+    });
+    assert.isDefined(firstColumnTitle);
+
     // Check that empty value was not appended.
     assert.lengthOf(table.$.body.children, 0);
   });
@@ -56,7 +63,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = [];
     table.emptyValue = 'This table is left intentionally empty';
@@ -97,7 +104,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = rows;
     table.emptyValue = 'THIS SHOULD NOT BE VISIBLE!!!';
@@ -143,7 +150,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = rows;
     table.footerRows = footerRows;
@@ -204,7 +211,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = rows;
     table.rebuild();
@@ -213,7 +220,7 @@
   });
 
   test('instantiateSortingCallbacksWithNests', function() {
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
 
     var columns = [
       {
@@ -351,18 +358,18 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = rows;
     table.rebuild();
     this.addHTMLOutput(table);
 
-    var a1El = tv.b.findDeepElementMatchingPredicate(table, function(element) {
+    var a1El = tr.b.findDeepElementMatchingPredicate(table, function(element) {
       return element.textContent == 'a1';
     });
     assert.isDefined(a1El);
 
-    var bToplevelEl = tv.b.findDeepElementMatchingPredicate(
+    var bToplevelEl = tr.b.findDeepElementMatchingPredicate(
         table,
         function(element) {
           return element.textContent == 'bToplevel';
@@ -396,7 +403,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = rows;
     table.rebuild();
@@ -425,7 +432,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.showHeader = false;
     table.tableColumns = columns;
     table.tableRows = rows;
@@ -459,7 +466,7 @@
       }
     ];
 
-    var table1 = document.createElement('tracing-analysis-nested-table');
+    var table1 = document.createElement('tr-b-ui-table');
     table1.showHeader = true;
 
     assert.throws(function() {
@@ -481,7 +488,7 @@
       }
     ];
 
-    var table1 = document.createElement('tracing-analysis-nested-table');
+    var table1 = document.createElement('tr-b-ui-table');
     table1.showHeader = true;
     table1.tableColumns = columns;
     table1.tableRows = [
@@ -493,7 +500,7 @@
     table1.rebuild();
     this.addHTMLOutput(table1);
 
-    var table2 = document.createElement('tracing-analysis-nested-table');
+    var table2 = document.createElement('tr-b-ui-table');
     table2.showHeader = false;
     table2.tableColumns = columns;
     table2.tableRows = [
@@ -512,7 +519,7 @@
   });
 
   test('programmaticSorting', function() {
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
 
     var columns = [
       {
@@ -570,7 +577,7 @@
   });
 
   test('sortingAfterExpand', function() {
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
 
     var columns = [
       {
@@ -634,7 +641,7 @@
   });
 
   function createSimpleOneColumnNestedTable() {
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
 
     var columns = [
       {
@@ -766,7 +773,7 @@
 
   test('reduceNumberOfColumnsAfterRebuild', function() {
     // Create a table with two columns.
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = [
       {
         title: 'First Column',
@@ -818,7 +825,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.showHeader = true;
     table.supportsSelection = true;
     table.cellSelectionMode = true;
@@ -876,7 +883,7 @@
       }
     ];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = rows;
     table.rebuild();
@@ -901,7 +908,7 @@
     ];
     var rows = [{a: 1}];
 
-    var table = document.createElement('tracing-analysis-nested-table');
+    var table = document.createElement('tr-b-ui-table');
     table.tableColumns = columns;
     table.tableRows = rows;
     table.rebuild();
@@ -910,5 +917,35 @@
 
     assert.equal('right', table.$.body.children[0].children[0].style.textAlign);
   });
+
+  test('subRowsPropertyName', function() {
+    var columns = [
+      {
+        title: 'a',
+        value: function(row) {
+          return row.a;
+        }
+      }
+    ];
+    var rows = [
+      {
+        a: 1,
+        isExpanded: true,
+        children: [
+          {a: 2}
+        ]
+      }
+    ];
+
+    var table = document.createElement('tr-b-ui-table');
+    table.subRowsPropertyName = 'children';
+    table.tableColumns = columns;
+    table.tableRows = rows;
+    table.rebuild();
+
+    this.addHTMLOutput(table);
+
+    assert.equal(2, table.$.body.children[1].children[0].textContent);
+  });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/base/ui_test.html b/trace-viewer/trace_viewer/base/ui_test.html
index 20234d4..faa421e 100644
--- a/trace-viewer/trace_viewer/base/ui_test.html
+++ b/trace-viewer/trace_viewer/base/ui_test.html
@@ -8,8 +8,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TestElement = tv.b.ui.define('div');
+tr.b.unittest.testSuite(function() {
+  var TestElement = tr.b.ui.define('div');
   TestElement.prototype = {
     __proto__: HTMLDivElement.prototype,
 
@@ -20,7 +20,7 @@
     }
   };
 
-  var Base = tv.b.ui.define('div');
+  var Base = tr.b.ui.define('div');
   Base.prototype = {
     __proto__: HTMLDivElement.prototype,
     decorate: function() {
@@ -38,17 +38,17 @@
 
   test('decorateOnceDirectly', function() {
     var testElement = document.createElement('div');
-    tv.b.ui.decorate(testElement, TestElement);
+    tr.b.ui.decorate(testElement, TestElement);
     assert.equal(testElement.decorateCallCount, 1);
   });
 
   test('componentToString', function() {
     assert.equal(Base.toString(), 'div');
 
-    var Sub = tv.b.ui.define('Sub', Base);
+    var Sub = tr.b.ui.define('Sub', Base);
     assert.equal(Sub.toString(), 'div::sub');
 
-    var SubSub = tv.b.ui.define('Marine', Sub);
+    var SubSub = tr.b.ui.define('Marine', Sub);
     assert.equal(SubSub.toString(), 'div::sub::marine');
   });
 
@@ -65,7 +65,7 @@
   });
 
   test('subclassing', function() {
-    var Sub = tv.b.ui.define('sub', Base);
+    var Sub = tr.b.ui.define('sub', Base);
     Sub.prototype = {
       __proto__: Base.prototype,
       decorate: function() {
@@ -87,7 +87,7 @@
     assert.isTrue(subInstance.basePropertySet);
   });
 
-  var NoArgs = tv.b.ui.define('div');
+  var NoArgs = tr.b.ui.define('div');
   NoArgs.prototype = {
     __proto__: HTMLDivElement.prototype,
     decorate: function() {
@@ -98,7 +98,7 @@
     }
   };
 
-  var Args = tv.b.ui.define('args', NoArgs);
+  var Args = tr.b.ui.define('args', NoArgs);
   Args.prototype = {
     __proto__: NoArgs.prototype,
     decorate: function(first) {
@@ -113,7 +113,7 @@
     }
   };
 
-  var ArgsChild = tv.b.ui.define('args-child', Args);
+  var ArgsChild = tr.b.ui.define('args-child', Args);
   ArgsChild.prototype = {
     __proto__: Args.prototype,
     decorate: function(_, second) {
@@ -131,7 +131,7 @@
     }
   };
 
-  var ArgsDecoratingChild = tv.b.ui.define('args-decorating-child', Args);
+  var ArgsDecoratingChild = tr.b.ui.define('args-decorating-child', Args);
   ArgsDecoratingChild.prototype = {
     __proto__: Args.prototype,
     decorate: function(first, second) {
@@ -187,7 +187,7 @@
 
   test('defineWithNamespace', function() {
     var svgNS = 'http://www.w3.org/2000/svg';
-    var cls = tv.b.ui.define('svg', undefined, svgNS);
+    var cls = tr.b.ui.define('svg', undefined, svgNS);
     cls.prototype = {
       __proto__: HTMLUnknownElement.prototype,
 
@@ -211,7 +211,7 @@
 
   test('defineSubclassWithNamespace', function() {
     var svgNS = 'http://www.w3.org/2000/svg';
-    var cls = tv.b.ui.define('svg', undefined, svgNS);
+    var cls = tr.b.ui.define('svg', undefined, svgNS);
     cls.prototype = {
       __proto__: HTMLUnknownElement.prototype,
 
@@ -228,7 +228,7 @@
       }
     };
 
-    var subCls = tv.b.ui.define('sub', cls);
+    var subCls = tr.b.ui.define('sub', cls);
     subCls.prototype = {
       __proto__: cls.prototype
     };
diff --git a/trace-viewer/trace_viewer/base/units/array_of_numbers_span.html b/trace-viewer/trace_viewer/base/units/array_of_numbers_span.html
new file mode 100644
index 0000000..d3a446d
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/array_of_numbers_span.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/statistics.html">
+<script>
+'use strict';
+tr.exportTo('tr.b.units', function() {
+  var ArrayOfNumbersSummaryModes = {
+    AVERAGE_MODE: 'average-mode',
+    TOTAL_MODE: 'total-mode'
+  };
+  return {
+    ArrayOfNumbersSummaryModes: ArrayOfNumbersSummaryModes
+  };
+});
+</script>
+<polymer-element name="tr-b-u-array-of-numbers-span">
+  <template>
+  </template>
+  <script>
+  'use strict';
+
+  Polymer({
+    created: function() {
+      this.numbers_ = undefined;
+      this.summaryMode_ = tr.b.units.ArrayOfNumbersSummaryModes.AVERAGE_MODE;
+    },
+
+    get summaryMode() {
+      return this.summaryMode_;
+    },
+
+    set summaryMode(summaryMode) {
+      this.summaryMode_ = summaryMode;
+      this.updateContents_();
+    },
+
+    get numbers() {
+      return this.numbers_;
+    },
+
+    set numbers(numbers) {
+      if (numbers === undefined) {
+        this.numbers_ = undefined;
+        this.updateContents_();
+        return;
+      }
+      if (!(numbers instanceof Array))
+        throw new Error('Must provide an array');
+      this.numbers_ = numbers;
+      this.updateContents_();
+    },
+
+    updateContents_: function() {
+      if (this.numbers_ === undefined) {
+        this.shadowRoot.textContent = '-';
+        return;
+      }
+
+      var ArrayOfNumbersSummaryModes = tr.b.units.ArrayOfNumbersSummaryModes;
+      var value;
+      if (this.summaryMode_ === ArrayOfNumbersSummaryModes.AVERAGE_MODE)
+        value = tr.b.Statistics.mean(this.numbers_);
+      else
+        value = tr.b.Statistics.sum(this.numbers_);
+
+      var valueRounded = Math.round(value * 1000.0) / 1000.0;
+      this.shadowRoot.textContent = valueRounded;
+    }
+  });
+  </script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/base/units/array_of_numbers_span_test.html b/trace-viewer/trace_viewer/base/units/array_of_numbers_span_test.html
new file mode 100644
index 0000000..a201bcc
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/array_of_numbers_span_test.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/units/array_of_numbers_span.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('instantiateInAverageMode', function() {
+    var span = document.createElement('tr-b-u-array-of-numbers-span');
+    span.numbers = [1, 2, 3];
+    span.summaryMode = tr.b.units.ArrayOfNumbersSummaryModes.AVERAGE_MODE;
+    this.addHTMLOutput(span);
+    assert.equal(span.shadowRoot.textContent, '2');
+  });
+
+  test('instantiateInTotalsMode', function() {
+    var span = document.createElement('tr-b-u-array-of-numbers-span');
+    span.numbers = [1, 2, 3];
+    span.summaryMode = tr.b.units.ArrayOfNumbersSummaryModes.TOTALS_MODE;
+    this.addHTMLOutput(span);
+    assert.equal(span.shadowRoot.textContent, '6');
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/generic_table.html b/trace-viewer/trace_viewer/base/units/generic_table.html
new file mode 100644
index 0000000..954de9e
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/generic_table.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.units', function() {
+  /**
+   * Tabular data wrapper. Simply wraps an array of items.
+   */
+  function GenericTable(items) {
+    if (items !== undefined)
+      this.items = items;
+    else
+      this.items = [];
+  };
+
+  GenericTable.prototype = {
+
+  };
+
+  return {
+    GenericTable: GenericTable
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/generic_table_view.html b/trace-viewer/trace_viewer/base/units/generic_table_view.html
new file mode 100644
index 0000000..006851a
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/generic_table_view.html
@@ -0,0 +1,227 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/iteration_helpers.html">
+<link rel="import" href="/base/statistics.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/units/generic_table.html">
+<link rel="import" href="/base/units/array_of_numbers_span.html">
+<polymer-element name="tr-b-u-generic-table-view">
+  <template>
+    <style>
+    :host {
+    display: flex;
+    }
+    #table {
+      flex: 1 1 auto;
+      align-self: stretch;
+    }
+    </style>
+    <tr-b-ui-table id="table"></tr-b-ui-table>
+  </template>
+</polymer-element>
+<script>
+'use strict';
+
+tr.exportTo('tr.b.units', function() {
+  var TEXT_COLUMN_MODE = 1;
+  var NUMERIC_COLUMN_MODE = 2;
+
+  function isNumeric(value) {
+    // TODO(nduca): Also consider other units that are numeric.
+    if ((typeof value) === 'number')
+      return true;
+    else if (value instanceof Number)
+      return true;
+    return false;
+  }
+
+  function GenericTableViewTotalsItem(opt_values) {
+    if (opt_values !== undefined)
+      this.values = opt_values;
+    else
+      this.values = [];
+  }
+
+  function GenericTableViewColumnDescriptor(fieldName, firstFieldValue) {
+    this.title = fieldName;
+    this.fieldName = fieldName;
+
+    this.updateModeGivenValue(firstFieldValue);
+  }
+
+  GenericTableViewColumnDescriptor.prototype = {
+    get columnMode() {
+      return this.columnMode_;
+    },
+
+    get isInNumericMode() {
+      return this.columnMode_ === NUMERIC_COLUMN_MODE;
+    },
+
+    cmp: function(a, b) {
+      return tr.b.comparePossiblyUndefinedValues(a, b, function(a, b) {
+        var vA = a[this.fieldName];
+        var vB = b[this.fieldName];
+        return tr.b.comparePossiblyUndefinedValues(vA, vB, function(vA, vB) {
+          if (vA.localeCompare)
+            return vA.localeCompare(vB);
+          return vA - vB;
+        }, this);
+      }, this);
+    },
+
+    updateModeGivenValue: function(fieldValue) {
+      if (this.columnMode_ === undefined) {
+        if (fieldValue === undefined || fieldValue === null)
+          return;
+
+        if (isNumeric(fieldValue))
+          this.columnMode_ = NUMERIC_COLUMN_MODE;
+        else
+          this.columnMode_ = TEXT_COLUMN_MODE;
+        return;
+      }
+
+      // Undefineds & nulls shouldn't change the mode.
+      if (fieldValue === undefined || fieldValue === null)
+        return;
+
+      // If we were already in numeric mode, then we don't
+      // need to put it into numeric mode again. And, if we were
+      // previously in text mode, then we can't go into numeric mode now.
+      if (isNumeric(fieldValue))
+        return;
+
+      this.columnMode_ = TEXT_COLUMN_MODE;
+    },
+
+    value: function(item) {
+      var fieldValue = item[this.fieldName];
+      if (fieldValue instanceof GenericTableViewTotalsItem) {
+        var span = document.createElement('tr-b-u-array-of-numbers-span');
+        span.summaryMode = tr.b.units.ArrayOfNumbersSummaryModes.TOTAL_MODE;
+        span.numbers = fieldValue.values;
+        return span;
+      }
+
+      if (fieldValue === undefined)
+        return '-';
+
+      // TODO(nduca): Use units objects if applicable.
+      return fieldValue;
+    }
+  };
+
+  Polymer('tr-b-u-generic-table-view', {
+    created: function() {
+      this.items_ = undefined;
+    },
+
+    get items() {
+      return this.items_;
+    },
+
+    set items(itemsOrGenericTable) {
+      if (itemsOrGenericTable === undefined) {
+        this.items_ = undefined;
+      } else if (itemsOrGenericTable instanceof Array) {
+        this.items_ = itemsOrGenericTable;
+      } else if (itemsOrGenericTable instanceof tr.b.units.GenericTable) {
+        this.items_ = itemsOrGenericTable.items;
+      }
+      this.updateContents_();
+    },
+
+    createColumns_: function() {
+      var columnsByName = {};
+      this.items_.forEach(function(item) {
+        tr.b.iterItems(item, function(itemFieldName, itemFieldValue) {
+          var colDesc = columnsByName[itemFieldName];
+          if (colDesc !== undefined) {
+            colDesc.updateModeGivenValue(itemFieldValue);
+            return;
+          }
+
+          colDesc = new GenericTableViewColumnDescriptor(
+              itemFieldName, itemFieldValue);
+          columnsByName[itemFieldName] = colDesc;
+        }, this);
+      }, this);
+
+      var columns = tr.b.dictionaryValues(columnsByName);
+      if (columns.length === 0)
+        return undefined;
+
+      // Sort by name.
+      columns.sort(function(a, b) {
+        return a.title.localeCompare(b.title);
+      });
+
+      // Set sizes. This is convoluted by the fact that the first
+      // table column must have fixed size.
+      var colWidthPercentage;
+      if (columns.length == 1)
+        colWidthPercentage = '100%';
+      else
+        colWidthPercentage = (100 / (columns.length - 1)).toFixed(3) + '%';
+      columns[0].width = '250px';
+      for (var i = 1; i < columns.length; i++)
+        columns[i].width = colWidthPercentage;
+
+      return columns;
+    },
+
+    createFooterRowsIfNeeded_: function(columns) {
+      // Make totals row if needed.
+      var hasColumnThatIsNumeric = columns.some(function(column) {
+        return column.isInNumericMode;
+      });
+      if (!hasColumnThatIsNumeric)
+        return [];
+
+      var totalsItems = {};
+      columns.forEach(function(column) {
+        if (!column.isInNumericMode)
+          return;
+        var totalsItem = new GenericTableViewTotalsItem();
+        this.items_.forEach(function(item) {
+          var fieldValue = item[column.fieldName];
+          if (fieldValue === undefined || fieldValue === null)
+            return;
+          totalsItem.values.push(fieldValue);
+        });
+        totalsItems[column.fieldName] = totalsItem;
+      }, this);
+
+      return [totalsItems];
+    },
+
+    updateContents_: function() {
+      var columns;
+      if (this.items_ !== undefined)
+        columns = this.createColumns_();
+
+      if (!columns) {
+        this.$.table.tableColumns = [];
+        this.$.table.tableRows = [];
+        this.$.table.footerRows = [];
+        return;
+      }
+
+      this.$.table.tableColumns = columns;
+      this.$.table.tableRows = this.items_;
+      this.$.table.footerRows = this.createFooterRowsIfNeeded_(columns);
+      this.$.table.rebuild();
+    }
+  });
+
+  return {
+    GenericTableViewTotalsItem: GenericTableViewTotalsItem,
+    GenericTableViewColumnDescriptor: GenericTableViewColumnDescriptor
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/generic_table_view_test.html b/trace-viewer/trace_viewer/base/units/generic_table_view_test.html
new file mode 100644
index 0000000..6fe1f91
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/generic_table_view_test.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 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="import" href="/base/units/generic_table_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  var GenericTableViewColumnDescriptor =
+      tr.b.units.GenericTableViewColumnDescriptor;
+  var GenericTableViewTotalsItem = tr.b.units.GenericTableViewTotalsItem;
+
+  test('descBasicNumericMode', function() {
+    var colDesc = new GenericTableViewColumnDescriptor('a');
+    assert.isFalse(colDesc.isInNumericMode);
+
+    colDesc.updateModeGivenValue(4);
+    assert.isTrue(colDesc.isInNumericMode);
+
+    colDesc.updateModeGivenValue(4);
+    assert.isTrue(colDesc.isInNumericMode);
+
+    colDesc.updateModeGivenValue(undefined);
+    colDesc.updateModeGivenValue(null);
+    assert.isTrue(colDesc.isInNumericMode);
+
+    colDesc.updateModeGivenValue('a');
+    assert.isFalse(colDesc.isInNumericMode);
+  });
+
+  test('descBasicNonNumericMode', function() {
+    var colDesc = new GenericTableViewColumnDescriptor('a');
+    assert.isFalse(colDesc.isInNumericMode);
+    colDesc.updateModeGivenValue(4);
+    assert.isTrue(colDesc.isInNumericMode);
+    colDesc.updateModeGivenValue('a');
+    assert.isFalse(colDesc.isInNumericMode);
+  });
+
+  test('descCmpWithNumbers', function() {
+    var colDesc = new GenericTableViewColumnDescriptor('a', 1);
+    assert.equal(colDesc.cmp({a: 1}, {a: 2}), -1);
+    assert.equal(colDesc.cmp({a: 1}, undefined), -1);
+  });
+
+  test('descCmpWithText', function() {
+    var colDesc = new GenericTableViewColumnDescriptor('a', 'text');
+    assert.equal(colDesc.cmp({a: 'a'}, {a: 'b'}), -1);
+    assert.equal(colDesc.cmp({a: 'a'}, undefined), -1);
+  });
+
+  test('descValue', function() {
+    var colDesc = new GenericTableViewColumnDescriptor('a', 1);
+    var value = colDesc.value({a: undefined});
+    assert.equal(value, '-');
+
+    value = colDesc.value({a: 3});
+    assert.equal(value, 3);
+
+    var totalsValue = colDesc.value(
+        {a: new GenericTableViewTotalsItem([1, 2, 3])});
+    assert.equal(totalsValue.tagName.toLowerCase(),
+                  'tr-b-u-array-of-numbers-span');
+    assert.deepEqual(totalsValue.numbers, [1, 2, 3]);
+  });
+
+  test('everythingTogether', function() {
+    var table = document.createElement('tr-b-u-generic-table-view');
+    table.items = [
+      {
+        a: 'someString',
+        b: 2,
+        c: 'adsf'
+      },
+      {
+        a: 'someOtherString',
+        b: 2,
+        c: 'adsf'
+      }
+    ];
+    this.addHTMLOutput(table);
+  });
+
+  test('summableColumn', function() {
+    var table = document.createElement('tr-b-u-generic-table-view');
+    table.items = [
+      {
+        a: 1
+      },
+      {
+        a: 2
+      },
+      {
+        a: 3
+      }
+    ];
+    this.addHTMLOutput(table);
+
+    assert.equal(table.$.table.tableColumns.length, 1);
+    assert.equal(table.$.table.tableRows.length, 3);
+    assert.isTrue(table.$.table.tableColumns[0].isInNumericMode);
+    assert.equal(table.$.table.tableColumns[0].fieldName, 'a');
+    var totalsItem = table.$.table.footerRows[0].a;
+    assert.deepEqual(totalsItem.values, [1, 2, 3]);
+  });
+
+
+  test('usingGenericTable', function() {
+    var table = document.createElement('tr-b-u-generic-table-view');
+    table.items = new tr.b.units.GenericTable([
+      {
+        a: 1
+      }
+    ]);
+    assert.equal(table.items.length, 1);
+  });
+
+  test('mixedTypeTable', function() {
+    var table = document.createElement('tr-b-u-generic-table-view');
+    table.items = [
+      {
+        a: 1
+      },
+      {
+        a: 2
+      },
+      {
+        b: 'c'
+      }
+    ];
+    this.addHTMLOutput(table);
+  });
+
+  test('emptyTable', function() {
+    var table = document.createElement('tr-b-u-generic-table-view');
+    table.items = [{}];
+    assert.equal(table.$.table.tableColumns.length, 0);
+  });
+
+  test('undefinedAndValue', function() {
+    var table = document.createElement('tr-b-u-generic-table-view');
+    table.items = [
+      {
+      },
+      {
+        a: 2
+      }
+    ];
+    this.addHTMLOutput(table);
+  });
+
+  test('undefinedOnly', function() {
+    var table = document.createElement('tr-b-u-generic-table-view');
+    table.items = [
+      {
+        a: undefined
+      }
+    ];
+    this.addHTMLOutput(table);
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/size_in_bytes.html b/trace-viewer/trace_viewer/base/units/size_in_bytes.html
new file mode 100644
index 0000000..642b5f1
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/size_in_bytes.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/iteration_helpers.html">
+<link rel="import" href="/base/rect.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.units', function() {
+  /**
+   * Float wrapper, representing a time stamps, capable of pretty-printing.
+   */
+  function SizeInBytes(numBytes) {
+    this.numBytes = numBytes;
+  };
+
+  SizeInBytes.prototype = {
+    toString: function() {
+      return this.numBytes.toFixed(0) + ' bytes';
+    }
+  };
+
+  return {
+    SizeInBytes: SizeInBytes
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/size_in_bytes_span.html b/trace-viewer/trace_viewer/base/units/size_in_bytes_span.html
new file mode 100644
index 0000000..fe662a6
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/size_in_bytes_span.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/units/size_in_bytes.html">
+<polymer-element name="tr-b-u-size-in-bytes-span">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+    }
+    </style>
+    <span id="content"></span>
+  </template>
+  <script>
+  'use strict';
+
+  Polymer({
+    ready: function() {
+      this.$.content.textContent = String.fromCharCode(9888);
+      this.numBytes_ = undefined;
+    },
+
+    get numBytes() {
+      return this.numBytes_;
+    },
+
+    set numBytes(numBytesOrSizeInBytes) {
+      if (numBytesOrSizeInBytes instanceof tr.b.units.SizeInBytes)
+        this.numBytes_ = numBytesOrSizeInBytes.numBytes;
+      else
+        this.numBytes_ = numBytesOrSizeInBytes;
+
+      var numBytes = this.numBytes;
+
+      var signPrefix = '';
+      if (numBytes < 0) {
+        signPrefix = '-';
+        numBytes = -numBytes;
+      }
+
+      var unitPrefixes = ['', 'Ki', 'Mi', 'Gi', 'Ti'];
+      var i = 0;
+      while (numBytes >= 1024 && i < unitPrefixes.length - 1) {
+        numBytes /= 1024;
+        i++;
+      }
+      var sizeString =
+          signPrefix + numBytes.toFixed(1) + ' ' + unitPrefixes[i] + 'B';
+
+      this.$.content.textContent = sizeString;
+    },
+
+    get stringContent() {
+      return this.$.content.textContent;
+    }
+  });
+  </script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/size_span_test.html b/trace-viewer/trace_viewer/base/units/size_in_bytes_span_test.html
similarity index 61%
rename from trace-viewer/trace_viewer/core/analysis/size_span_test.html
rename to trace-viewer/trace_viewer/base/units/size_in_bytes_span_test.html
index a030cab..47c76d1 100644
--- a/trace-viewer/trace_viewer/core/analysis/size_span_test.html
+++ b/trace-viewer/trace_viewer/base/units/size_in_bytes_span_test.html
@@ -4,21 +4,28 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/core/analysis/size_span.html">
+<link rel="import" href="/base/units/size_in_bytes_span.html">
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
   test('instantiate', function() {
-    var timeSpan = document.createElement('tv-c-a-size-span');
+    var timeSpan = document.createElement('tr-b-u-size-in-bytes-span');
     timeSpan.numBytes = 5 * 1024;
     assert.equal(timeSpan.numBytes, 5 * 1024);
     this.addHTMLOutput(timeSpan);
   });
 
+  test('instantiateWithObject', function() {
+    var timeSpan = document.createElement('tr-b-u-size-in-bytes-span');
+    timeSpan.numBytes = new tr.b.units.SizeInBytes(5 * 1024);
+    assert.equal(timeSpan.numBytes, 5 * 1024);
+    this.addHTMLOutput(timeSpan);
+  });
+
   test('sizeStrings', function() {
-    var el = document.createElement('tv-c-a-size-span');
+    var el = document.createElement('tr-b-u-size-in-bytes-span');
 
     el.numBytes = 0;
     assert.equal(el.stringContent, '0.0 B');
@@ -38,6 +45,9 @@
     el.numBytes = 1025 * 1024 * 1024 * 1024 * 1024;
     assert.equal(el.stringContent, '1025.0 TiB');
     this.addHTMLOutput(el);
+
+    el.numBytes = -2.5 * 1024 * 1024;
+    assert.equal(el.stringContent, '-2.5 MiB');
   });
 
 });
diff --git a/trace-viewer/trace_viewer/base/units/time.html b/trace-viewer/trace_viewer/base/units/time.html
new file mode 100644
index 0000000..abdadf0
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/time.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>

+<!--

+Copyright (c) 2015 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="import" href="/base/base.html">

+<link rel="import" href="/base/event_target.html">

+

+<script>

+'use strict';

+

+/**

+ * @fileoverview Time currentDisplayUnit

+ */

+tr.exportTo('tr.b.units', function() {

+  var ms = {

+    suffix: 'ms',

+    format: function(ts) {

+      var tsRounded = Math.round(ts * 1000.0) / 1000.0;

+      var n = new Number(tsRounded);

+      return n.toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' ms';

+    }

+  };

+

+  var ns = {

+    suffix: 'ns',

+    format: function(ts) {

+      var tsRounded = Math.round(ts * 1000000.0);

+      var n = new Number(tsRounded);

+      return n.toLocaleString(undefined, { maximumFractionDigits: 0 }) + ' ns';

+    }

+  };

+

+  var Time = {

+    supportedUnits: {

+      ms: ms,

+      ns: ns

+    },

+

+    reset: function() {

+      this.currentDisplayUnit = ms;

+    },

+

+    currentDisplayUnit_: ms,

+    get currentDisplayUnit() {

+      return this.currentDisplayUnit_;

+    },

+    set currentDisplayUnit(value) {

+      if (this.currentDisplayUnit_ == value)

+        return;

+

+      this.currentDisplayUnit_ = value;

+      this.dispatchEvent(new Event('display-unit-changed'));

+    }

+  };

+

+  tr.b.EventTarget.decorate(Time);

+

+  return {

+    Time: Time

+  };

+});

+</script>

diff --git a/trace-viewer/trace_viewer/base/time.html b/trace-viewer/trace_viewer/base/units/time_duration.html
similarity index 72%
rename from trace-viewer/trace_viewer/base/time.html
rename to trace-viewer/trace_viewer/base/units/time_duration.html
index 5ba58dd..1711037 100644
--- a/trace-viewer/trace_viewer/base/time.html
+++ b/trace-viewer/trace_viewer/base/units/time_duration.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b.units', function() {
   /**
    * Float wrapper, representing a time duration, capable of pretty-printing.
    */
@@ -23,18 +23,7 @@
     }
   };
 
-  function TimeStamp(timestamp) {
-    this.timestamp = timestamp;
-  };
-
-  TimeStamp.prototype = {
-    toString: function() {
-      return this.timestamp.toFixed(4) + ' ms';
-    }
-  };
-
   return {
-    TimeStamp: TimeStamp,
     TimeDuration: TimeDuration
   };
 });
diff --git a/trace-viewer/trace_viewer/base/units/time_duration_span.html b/trace-viewer/trace_viewer/base/units/time_duration_span.html
new file mode 100644
index 0000000..902faea
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/time_duration_span.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/deep_utils.html">
+<link rel="import" href="/base/units/time.html">
+<link rel="import" href="/base/units/time_duration.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.b.units', function() {
+  function createTimeSpan(duration) {
+    if (duration === undefined)
+      return '';
+    var span = document.createElement('tr-b-u-time-duration-span');
+    span.duration = duration;
+    return span;
+  }
+
+  tr.b.units.Time.addEventListener('display-unit-changed', function(e) {
+    tr.b.findDeepElementsMatching(document.body,
+      'tr-b-u-time-duration-span').forEach(function(el) {
+        el.updateContent_();
+      });
+  });
+
+  return {
+    createTimeSpan: createTimeSpan
+  };
+});
+</script>
+
+<polymer-element name="tr-b-u-time-duration-span">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+    }
+    #warning {
+      margin-left: 4px;
+      font-size: 66%;
+    }
+    </style>
+    <span id="content"></span>
+    <span id="warning" style="display:none">&#9888;</span>
+  </template>
+  <script>
+  'use strict';
+
+  Polymer({
+    ready: function() {
+      this.warning_ = undefined;
+      this.duration_ = undefined;
+    },
+
+    get duration() {
+      return this.duration_;
+    },
+
+    set duration(duration) {
+      if (duration instanceof tr.b.units.TimeDuration)
+        this.duration_ = duration.duration;
+      else
+        this.duration_ = duration;
+      this.updateContent_();
+    },
+
+    updateContent_: function() {
+      var content = tr.b.units.Time.currentDisplayUnit.format(this.duration_);
+      this.$.content.textContent = content;
+    },
+
+    get warning() {
+      return this.warning_;
+    },
+
+    set warning(warning) {
+      this.warning_ = warning;
+      var warningEl = this.$.warning;
+      if (this.warning_) {
+        warningEl.title = warning;
+        warningEl.style.display = '';
+      } else {
+        warningEl.title = '';
+        warningEl.style.display = 'none';
+      }
+    }
+  });
+  </script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/base/units/time_duration_span_test.html b/trace-viewer/trace_viewer/base/units/time_duration_span_test.html
new file mode 100644
index 0000000..a535fef
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/time_duration_span_test.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/units/time.html">
+<link rel="import" href="/base/units/time_duration_span.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('instantiate', function() {
+    var timeSpan = document.createElement('tr-b-u-time-duration-span');
+    timeSpan.duration = 73;
+    this.addHTMLOutput(timeSpan);
+  });
+  test('instantiateWitHObject', function() {
+    var timeSpan = document.createElement('tr-b-u-time-duration-span');
+    timeSpan.duration = new tr.b.units.TimeDuration(73);
+    this.addHTMLOutput(timeSpan);
+    assert.equal(timeSpan.duration, 73);
+  });
+  test('instantiateWithWarning', function() {
+    var timeSpan = document.createElement('tr-b-u-time-duration-span');
+    timeSpan.duration = 400;
+    timeSpan.warning = 'there is a problem with this time';
+    this.addHTMLOutput(timeSpan);
+  });
+
+  test('warningAndNonWarningHaveSimilarHeights', function() {
+    var spanA = document.createElement('tr-b-u-time-duration-span');
+    spanA.duration = 400;
+
+    var spanB = document.createElement('tr-b-u-time-duration-span');
+    spanB.duration = 400;
+    spanB.warning = 'there is a problem with this time';
+
+    var overall = document.createElement('div');
+    overall.style.display = 'flex';
+    overall.appendChild(spanA);
+    spanB.style.marginLeft = '4px';
+    overall.appendChild(spanB);
+    this.addHTMLOutput(overall);
+  });
+
+
+  test('respectCurrentDisplayUnit', function() {
+    try {
+      var Time = tr.b.units.Time;
+      Time.currentDisplayUnit = Time.supportedUnits.ns;
+
+      var timeSpan = document.createElement('tr-b-u-time-duration-span');
+      timeSpan.duration = 73;
+      this.addHTMLOutput(timeSpan);
+
+      assert.isTrue(timeSpan.$.content.textContent.indexOf('ns') > 0);
+      Time.currentDisplayUnit = Time.supportedUnits.ms;
+      assert.isTrue(timeSpan.$.content.textContent.indexOf('ms') > 0);
+    } finally {
+      Time.reset();
+    }
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/time_stamp.html b/trace-viewer/trace_viewer/base/units/time_stamp.html
new file mode 100644
index 0000000..402061d
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/time_stamp.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/iteration_helpers.html">
+<link rel="import" href="/base/rect.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.units', function() {
+  /**
+   * Float wrapper, representing a time stamps, capable of pretty-printing.
+   */
+  function TimeStamp(timestamp) {
+    this.timestamp = timestamp;
+  };
+
+  TimeStamp.prototype = {
+    toString: function() {
+      return this.timestamp.toFixed(4) + ' ms';
+    }
+  };
+
+  return {
+    TimeStamp: TimeStamp
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/time_stamp_span.html b/trace-viewer/trace_viewer/base/units/time_stamp_span.html
new file mode 100644
index 0000000..450d2a9
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/time_stamp_span.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/deep_utils.html">
+<link rel="import" href="/base/units/time.html">
+<link rel="import" href="/base/units/time_stamp.html">
+<script>
+'use strict';
+tr.exportTo('tr.b.units', function() {
+  function createTimeStampSpan(timestamp) {
+    if (timestamp === undefined)
+      return '';
+    var span = document.createElement('tr-b-u-time-stamp-span');
+    span.timestamp = timestamp;
+    return span;
+  }
+
+  tr.b.units.Time.addEventListener('display-unit-changed', function(e) {
+    tr.b.findDeepElementsMatching(document.body,
+      'tr-b-u-time-stamp-span').forEach(function(el) {
+        el.updateContent_();
+      });
+  });
+
+  return {
+    createTimeStampSpan: createTimeStampSpan
+  };
+});
+</script>
+
+<polymer-element name="tr-b-u-time-stamp-span">
+  <template>
+  </template>
+  <script>
+  'use strict';
+
+  Polymer({
+    ready: function() {
+      this.timestamp_ = undefined;
+    },
+
+    get timestamp() {
+      return this.timestamp_;
+    },
+
+    set timestamp(timestamp) {
+      if (timestamp instanceof tr.b.units.TimeStamp)
+        this.timestamp_ = timestamp.timestamp;
+      else
+        this.timestamp_ = timestamp;
+      this.updateContent_();
+    },
+
+    updateContent_: function() {
+      var content = tr.b.units.Time.currentDisplayUnit.format(this.timestamp_);
+      this.shadowRoot.textContent = content;
+    }
+  });
+  </script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/base/units/time_stamp_span_test.html b/trace-viewer/trace_viewer/base/units/time_stamp_span_test.html
new file mode 100644
index 0000000..5402b67
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/time_stamp_span_test.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/units/time.html">
+<link rel="import" href="/base/units/time_stamp_span.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('instantiate', function() {
+    var timeStamp = document.createElement('tr-b-u-time-stamp-span');
+    timeStamp.timestamp = 73;
+    this.addHTMLOutput(timeStamp);
+  });
+  test('instantiateWithObject', function() {
+    var timeStamp = document.createElement('tr-b-u-time-stamp-span');
+    timeStamp.timestamp = new tr.b.units.TimeStamp(73);
+    this.addHTMLOutput(timeStamp);
+    assert.equal(timeStamp.timestamp, 73);
+  });
+
+  test('respectCurrentDisplayUnit', function() {
+    try {
+      var Time = tr.b.units.Time;
+      Time.currentDisplayUnit = Time.supportedUnits.ns;
+
+      var timeStamp = document.createElement('tr-b-u-time-stamp-span');
+      timeStamp.timestamp = 73;
+      this.addHTMLOutput(timeStamp);
+
+      assert.isTrue(timeStamp.shadowRoot.textContent.indexOf('ns') > 0);
+      Time.currentDisplayUnit = Time.supportedUnits.ms;
+      assert.isTrue(timeStamp.shadowRoot.textContent.indexOf('ms') > 0);
+    } finally {
+      Time.reset();
+    }
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/time_test.html b/trace-viewer/trace_viewer/base/units/time_test.html
new file mode 100644
index 0000000..a0a7774
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/time_test.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/units/time.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('Time.ms.format', function() {
+    function local(v) {
+      return v.toLocaleString(undefined, { minimumFractionDigits: 3}) + ' ms';
+    }
+
+    var unit = tr.b.units.Time.supportedUnits.ms;
+    assert.equal(unit.format(1), local(1));
+    assert.equal(unit.format(1.001), local(1.001));
+    assert.equal(unit.format(1.0005), local(1.001));
+    assert.equal(unit.format(1.0004), local(1));
+    assert.equal(unit.format(0.999), local(0.999));
+    assert.equal(unit.format(0.9995), local(1));
+  });
+
+  test('Time.ns.format', function() {
+    function local(v) {
+      return v.toLocaleString(undefined, { maximumFractionDigits: 0}) + ' ns';
+    }
+
+    var unit = tr.b.units.Time.supportedUnits.ns;
+    assert.equal(unit.format(1), local(1000000));
+    assert.equal(unit.format(0.001), local(1000));
+    assert.equal(unit.format(0.000001), local(1));
+    assert.equal(unit.format(0.0000005), local(1));
+    assert.equal(unit.format(0.0000004), local(0));
+    assert.equal(unit.format(0.0000015), local(2));
+  });
+
+  test('Time.display-unit-changed', function() {
+    var Time = tr.b.units.Time;
+
+    var listenerWasCalled = false;
+    function listener(e) {
+      listenerWasCalled = true;
+    }
+
+    try {
+      Time.currentDisplayUnit = Time.supportedUnits.ms;
+      Time.addEventListener('display-unit-changed', listener);
+
+      listenerWasCalled = false;
+      Time.currentDisplayUnit = Time.supportedUnits.ns;
+      assert.isTrue(listenerWasCalled);
+      assert.equal(Time.currentDisplayUnit, Time.supportedUnits.ns);
+    } finally {
+      Time.removeEventListener('display-unit-changed', listener);
+      Time.reset();
+    }
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/units/util.html b/trace-viewer/trace_viewer/base/units/util.html
new file mode 100644
index 0000000..77a5997
--- /dev/null
+++ b/trace-viewer/trace_viewer/base/units/util.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/base.html">
+<link rel="import" href="/base/units/time.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Deprecated, use the other units classes.
+ */
+tr.exportTo('tr.b.units', function() {
+  function tsString(ts) {
+    return tr.b.units.Time.currentDisplayUnit.format(ts);
+  }
+
+  return {
+    tsString: tsString
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/base/unittest.html b/trace-viewer/trace_viewer/base/unittest.html
index b5c7f5d..b696092 100644
--- a/trace-viewer/trace_viewer/base/unittest.html
+++ b/trace-viewer/trace_viewer/base/unittest.html
@@ -17,7 +17,7 @@
 <link rel="import" href="/base/unittest/test_runner.html">
 <script>
 'use strict';
-tv.exportTo('tv.b.unittest', function() {
+tr.exportTo('tr.b.unittest', function() {
   return {
   };
 });
diff --git a/trace-viewer/trace_viewer/base/unittest/constants.html b/trace-viewer/trace_viewer/base/unittest/constants.html
index 709ddb5..5679168 100644
--- a/trace-viewer/trace_viewer/base/unittest/constants.html
+++ b/trace-viewer/trace_viewer/base/unittest/constants.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.unittest', function() {
+tr.exportTo('tr.b.unittest', function() {
   var TestStatus = {
     PENDING: 'pending-status',
     RUNNING: 'running-status',
diff --git a/trace-viewer/trace_viewer/base/unittest/html_test_results.html b/trace-viewer/trace_viewer/base/unittest/html_test_results.html
index d178b2b..b7e07d4 100644
--- a/trace-viewer/trace_viewer/base/unittest/html_test_results.html
+++ b/trace-viewer/trace_viewer/base/unittest/html_test_results.html
@@ -10,12 +10,12 @@
 <link rel="import" href="/base/ui.html">
 <link rel="stylesheet" href="/base/unittest/common.css">
 <style>
-  x-tv.b.unittest-test-resultsbase
+  x-tr.b.unittest-test-resultsbase
     display: -webkit-flex;
     -webkit-flex-direction: column;
   }
 
-  x-tv.b.unittest-test-results > x-html-test-case-result.dark {
+  x-tr.b.unittest-test-results > x-html-test-case-result.dark {
     background-color: #eee;
   }
 
@@ -59,22 +59,22 @@
 
 <script>
 'use strict';
-tv.exportTo('tv.b.unittest', function() {
+tr.exportTo('tr.b.unittest', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
-  var TestStatus = tv.b.unittest.TestStatus;
-  var TestTypes = tv.b.unittest.TestTypes;
+  var TestStatus = tr.b.unittest.TestStatus;
+  var TestTypes = tr.b.unittest.TestTypes;
 
   /**
    * @constructor
    */
-  var HTMLTestCaseResult = tv.b.ui.define('x-html-test-case-result');
+  var HTMLTestCaseResult = tr.b.ui.define('x-html-test-case-result');
 
   HTMLTestCaseResult.prototype = {
     __proto__: HTMLUnknownElement.prototype,
 
     decorate: function() {
-      this.appendChild(tv.b.instantiateTemplate(
+      this.appendChild(tr.b.instantiateTemplate(
           '#x-html-test-case-result-template', THIS_DOC));
       this.testCase_ = undefined;
       this.testCaseHRef_ = undefined;
@@ -128,7 +128,7 @@
 
     addError: function(normalizedException) {
       var errorEl = document.createElement('x-html-test-case-error');
-      errorEl.appendChild(tv.b.instantiateTemplate(
+      errorEl.appendChild(tr.b.instantiateTemplate(
           '#x-html-test-case-error-template', THIS_DOC));
       errorEl.querySelector('#stack').textContent = normalizedException.stack;
       this.querySelector('#details').appendChild(errorEl);
@@ -221,7 +221,7 @@
   /**
    * @constructor
    */
-  var HTMLTestResults = tv.b.ui.define('x-tv.b.unittest-test-results');
+  var HTMLTestResults = tr.b.ui.define('x-tr.b.unittest-test-results');
 
   HTMLTestResults.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -334,7 +334,7 @@
     addErrorForCurrentTest: function(error) {
       this.log_('\n');
 
-      var normalizedException = tv.b.normalizeException(error);
+      var normalizedException = tr.b.normalizeException(error);
       this.log_('Exception: ' + normalizedException.message + '\n' +
           normalizedException.stack);
 
@@ -363,11 +363,11 @@
       if (testCaseResult.hadErrors) {
         this.log_('[FAILED]\n');
         this.numTestsThatFailed_ += 1;
-        tv.b.dispatchSimpleEvent(this, 'testfailed');
+        tr.b.dispatchSimpleEvent(this, 'testfailed');
       } else {
         this.log_('[PASSED]\n');
         this.numTestsThatPassed_ += 1;
-        tv.b.dispatchSimpleEvent(this, 'testpassed');
+        tr.b.dispatchSimpleEvent(this, 'testpassed');
       }
 
       if (this.headless_) {
@@ -414,7 +414,7 @@
 
     log_: function(msg) {
       //this.textContent += msg;
-      tv.b.dispatchSimpleEvent(this, 'statschange');
+      tr.b.dispatchSimpleEvent(this, 'statschange');
     }
   };
 
diff --git a/trace-viewer/trace_viewer/base/unittest/interactive_test_runner.html b/trace-viewer/trace_viewer/base/unittest/interactive_test_runner.html
index 7044aab..61b9a11 100644
--- a/trace-viewer/trace_viewer/base/unittest/interactive_test_runner.html
+++ b/trace-viewer/trace_viewer/base/unittest/interactive_test_runner.html
@@ -99,14 +99,14 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.unittest', function() {
+tr.exportTo('tr.b.unittest', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
   var ALL_TEST_TYPES = 'all';
 
   /**
    * @constructor
    */
-  var InteractiveTestRunner = tv.b.ui.define('x-base-interactive-test-runner');
+  var InteractiveTestRunner = tr.b.ui.define('x-base-interactive-test-runner');
 
   InteractiveTestRunner.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -117,7 +117,7 @@
       this.suppressStateChange_ = false;
 
       this.testFilterString_ = '';
-      this.testTypeToRun_ = tv.b.unittest.TestTypes.UNITTEST;
+      this.testTypeToRun_ = tr.b.unittest.TestTypes.UNITTEST;
       this.shortFormat_ = false;
       this.testSuiteName_ = '';
 
@@ -131,12 +131,12 @@
       this.onTestPassed_ = this.onTestPassed_.bind(this);
 
 
-      this.appendChild(tv.b.instantiateTemplate(
+      this.appendChild(tr.b.instantiateTemplate(
           '#x-base-interactive-test-runner-template', THIS_DOC));
 
       this.querySelector(
           'input[name=test-type-to-run][value=unit]').checked = true;
-      var testTypeToRunEls = tv.b.asArray(this.querySelectorAll(
+      var testTypeToRunEls = tr.b.asArray(this.querySelectorAll(
           'input[name=test-type-to-run]'));
 
       testTypeToRunEls.forEach(
@@ -196,7 +196,7 @@
       this.testFilterString_ = testFilterString;
       this.scheduleRerun_();
       if (!this.suppressStateChange_)
-        tv.b.dispatchSimpleEvent(this, 'statechange');
+        tr.b.dispatchSimpleEvent(this, 'statechange');
     },
 
     get shortFormat() {
@@ -209,7 +209,7 @@
       if (this.results_)
         this.results_.shortFormat = shortFormat;
       if (!this.suppressStateChange_)
-        tv.b.dispatchSimpleEvent(this, 'statechange');
+        tr.b.dispatchSimpleEvent(this, 'statechange');
     },
 
     onShortFormatClick_: function(e) {
@@ -217,7 +217,7 @@
       this.updateShortFormResultsDisplay_();
       this.updateResultsGivenShortFormat_();
       if (!this.suppressStateChange_)
-        tv.b.dispatchSimpleEvent(this, 'statechange');
+        tr.b.dispatchSimpleEvent(this, 'statechange');
     },
 
     updateShortFormResultsDisplay_: function() {
@@ -244,10 +244,10 @@
       this.testTypeToRun_ = testTypeToRun;
       var sel;
       switch (testTypeToRun) {
-        case tv.b.unittest.TestTypes.UNITTEST:
+        case tr.b.unittest.TestTypes.UNITTEST:
           sel = 'input[name=test-type-to-run][value=unit]';
           break;
-        case tv.b.unittest.TestTypes.PERFTEST:
+        case tr.b.unittest.TestTypes.PERFTEST:
           sel = 'input[name=test-type-to-run][value=perf]';
           break;
         case ALL_TEST_TYPES:
@@ -259,16 +259,16 @@
       this.querySelector(sel).checked = true;
       this.scheduleRerun_();
       if (!this.suppressStateChange_)
-        tv.b.dispatchSimpleEvent(this, 'statechange');
+        tr.b.dispatchSimpleEvent(this, 'statechange');
     },
 
     onTestTypeToRunClick_: function(e) {
       switch (e.target.value) {
         case 'unit':
-          this.testTypeToRun_ = tv.b.unittest.TestTypes.UNITTEST;
+          this.testTypeToRun_ = tr.b.unittest.TestTypes.UNITTEST;
           break;
         case 'perf':
-          this.testTypeToRun_ = tv.b.unittest.TestTypes.PERFTEST;
+          this.testTypeToRun_ = tr.b.unittest.TestTypes.PERFTEST;
           break;
         case 'all':
           this.testTypeToRun_ = ALL_TEST_TYPES;
@@ -279,7 +279,7 @@
 
       this.scheduleRerun_();
       if (!this.suppressStateChange_)
-        tv.b.dispatchSimpleEvent(this, 'statechange');
+        tr.b.dispatchSimpleEvent(this, 'statechange');
     },
 
     onTestPassed_: function() {
@@ -333,7 +333,7 @@
         resultsContainer.removeChild(this.results_);
       }
 
-      this.results_ = new tv.b.unittest.HTMLTestResults();
+      this.results_ = new tr.b.unittest.HTMLTestResults();
       this.results_.headless = this.headless_;
       this.results_.getHRefForTestCase = this.getHRefForTestCase.bind(this);
       this.updateResultsGivenShortFormat_();
@@ -357,7 +357,7 @@
         return true;
       }, this);
 
-      this.runner_ = new tv.b.unittest.TestRunner(this.results_, tests);
+      this.runner_ = new tr.b.unittest.TestRunner(this.results_, tests);
       this.runner_.beginRunning();
 
       this.runner_.runCompletedPromise.then(
@@ -378,7 +378,7 @@
         this.shortFormat = state.shortFormat;
 
       if (state.testTypeToRun === undefined)
-        this.testTypeToRun = tv.b.unittest.TestTypes.UNITTEST;
+        this.testTypeToRun = tr.b.unittest.TestTypes.UNITTEST;
       else
         this.testTypeToRun = state.testTypeToRun;
 
@@ -398,7 +398,7 @@
         testFilterString: '',
         testSuiteName: '',
         shortFormat: false,
-        testTypeToRun: tv.b.unittest.TestTypes.UNITTEST
+        testTypeToRun: tr.b.unittest.TestTypes.UNITTEST
       };
     },
 
diff --git a/trace-viewer/trace_viewer/base/unittest/module_test_case_runner.html b/trace-viewer/trace_viewer/base/unittest/module_test_case_runner.html
deleted file mode 100644
index 122225f..0000000
--- a/trace-viewer/trace_viewer/base/unittest/module_test_case_runner.html
+++ /dev/null
@@ -1,104 +0,0 @@
-<!DOCTYPE html>
-<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.
--->
-<head>
-  <title>trace-viewer/module_test_case_backend.html</title>
-  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-
-  <script src="/components/webcomponentsjs/webcomponents.js"></script>
-
-  <link rel="import" href="/components/polymer/polymer.html">
-  <link rel="import" href="/base/unittest.html">
-  <link rel="import" href="/base/unittest/text_test_results.html">
-  <link rel="import" href="/base/unittest/suite_loader.html">
-  <link rel="import" href="/base/unittest/test_runner.html">
-</head>
-<body>
-  <h1 id="status">
-  </h1>
-  <script>
-    'use strict';
-    /**
-     * Polled by tv.module_test_case
-     */
-    window.__readyToRun = false;
-
-    var statusEl = document.querySelector('#status');
-    function discoverTestsInModules(testModuleNames) {
-      statusEl.textContent = 'Discovering tests...';
-      var loader = new tv.b.unittest.SuiteLoader(testModuleNames);
-      return loader.allSuitesLoadedPromise.then(function() {
-        return loader.getAllTests().filter(function(test) {
-          return test.testType == tv.b.unittest.TestTypes.UNITTEST;
-        }).map(function(test) {
-          statusEl.textContent = 'Idle';
-          return test.fullyQualifiedName;
-        });
-      });
-    }
-
-    function runTestNamed(fullyQualifiedTestName) {
-      statusEl.textContent = 'Running ' + fullyQualifiedTestName;
-      function cleanup() {
-        statusEl.textContent = '';
-      }
-      return _runTestNamedImpl(fullyQualifiedTestName).then(
-        cleanup, cleanup);
-    }
-
-    function _runTestNamedImpl(fullyQualifiedTestName) {
-      var p = tv.b.unittest.TestCase.parseFullyQualifiedName(
-          fullyQualifiedTestName);
-      var suiteNameToLoad = p.suiteName;
-      var testCaseNameToRun = p.testCaseName;
-
-      var runTestResolver;
-      var runTestPromise = new Promise(function(resolve, reject) {
-        runTestResolver = {
-          resolve: resolve,
-          reject: reject
-        };
-      });
-
-      var loader = new tv.b.unittest.SuiteLoader([suiteNameToLoad]);
-      loader.allSuitesLoadedPromise.then(
-        beginRunningTestCase,
-        loadSuiteFailed);
-
-      var results = new tv.b.unittest.TextTestResults();
-      function loadSuiteFailed(e) {
-        var normalizedException = tv.b.normalizeException(e);
-        runTestResolver.reject(e);
-      }
-
-      function beginRunningTestCase() {
-        var testCase = loader.findTestWithFullyQualifiedName(
-            fullyQualifiedTestName);
-        var runner = new tv.b.unittest.TestRunner(results, [testCase]);
-        runner.beginRunning();
-        return runner.runCompletedPromise.then(
-          runTestCaseComplete,
-          runTestCaseComplete);
-      }
-
-      function runTestCaseComplete() {
-        if (results.numTestsThatFailed === 0) {
-          runTestResolver.resolve();
-          return;
-        }
-
-        runTestResolver.reject(results.buffer);
-      }
-      return runTestPromise;
-    }
-
-    window.addEventListener('load', function() {
-      window.__readyToRun = true;
-    });
-  </script>
-</body>
-</html>
diff --git a/trace-viewer/trace_viewer/base/unittest/suite_loader.html b/trace-viewer/trace_viewer/base/unittest/suite_loader.html
index eff10c2..c779464 100644
--- a/trace-viewer/trace_viewer/base/unittest/suite_loader.html
+++ b/trace-viewer/trace_viewer/base/unittest/suite_loader.html
@@ -11,14 +11,14 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.unittest', function() {
+tr.exportTo('tr.b.unittest', function() {
   function TestLink(linkPath, title) {
     this.linkPath = linkPath;
     this.title = title;
   }
 
   function SuiteLoader(opt_suiteNamesToLoad) {
-    tv.b.EventTarget.call(this);
+    tr.b.EventTarget.call(this);
 
     this.testSuiteGUIDs_ = {};
     this.testSuites = [];
@@ -33,12 +33,12 @@
           tmp);
     } else {
       var p;
-      p = tv.b.getAsync('/tv/json/tests');
+      p = tr.b.getAsync('/tr/json/tests');
       p = p.then(
           function(data) {
             var testMetadata = JSON.parse(data);
             if (testMetadata.hasOwnProperty('test_module_names')) {
-              tv.showPanic(
+              tr.showPanic(
                   'out of date webserver',
                   '>_< your devserver needs a restart kthxbai');
             }
@@ -58,7 +58,7 @@
       importEl.moduleName = moduleName;
       importEl.setAttribute('rel', 'import');
       importEl.setAttribute('href', href);
-      tv.doc.head.appendChild(importEl);
+      tr.doc.head.appendChild(importEl);
 
       importEl.addEventListener('load', function() {
         resolve(importEl);
@@ -77,7 +77,7 @@
   }
 
   SuiteLoader.prototype = {
-    __proto__: tv.b.EventTarget.prototype,
+    __proto__: tr.b.EventTarget.prototype,
 
     beginLoadingModules_: function(testRelpaths, opt_testMetadata) {
       if (opt_testMetadata) {
@@ -171,8 +171,8 @@
     },
 
     didImportElementGetLoaded_: function(importEl) {
-      // The global tv.testSute function stashes test suites
-      // onto the _tv array.
+      // The global tr.testSute function stashes test suites
+      // onto the _tr array.
       var importDoc = importEl.import;
       var suites = allTestSuitesByModuleURL[importDoc.URL];
       suites.forEach(function(testSuite) {
@@ -231,7 +231,7 @@
     if (!document.currentScript)
       throw new Error('Cannot call testSuite except during load.');
 
-    var testSuite = new tv.b.unittest.TestSuite(
+    var testSuite = new tr.b.unittest.TestSuite(
       name, suiteConstructor);
 
 
diff --git a/trace-viewer/trace_viewer/base/unittest/test_case.html b/trace-viewer/trace_viewer/base/unittest/test_case.html
index dd21b6c..9bc217a 100644
--- a/trace-viewer/trace_viewer/base/unittest/test_case.html
+++ b/trace-viewer/trace_viewer/base/unittest/test_case.html
@@ -9,13 +9,13 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.unittest', function() {
-  var TestTypes = tv.b.unittest.TestTypes;
+tr.exportTo('tr.b.unittest', function() {
+  var TestTypes = tr.b.unittest.TestTypes;
 
   function TestCase(name, opt_testFn, opt_options) {
     if (!name)
       throw new Error('Name must be provided');
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
     this.suite_ = undefined; // Set by TestSuite.addTest.
     this.name_ = name;
 
@@ -87,7 +87,7 @@
     // TODO(nduca): The routing of this is a bit awkward. Probably better
     // to install a global function.
     addHTMLOutput: function(element) {
-      tv.b.unittest.addHTMLOutputForCurrentTest(element);
+      tr.b.unittest.addHTMLOutputForCurrentTest(element);
     }
   };
 
@@ -116,8 +116,8 @@
       var durationStrings = durations.map(function(d) {
         return d.toFixed(2) + 'ms';
       });
-      var average = tv.b.Statistics.mean(durations);
-      var min = tv.b.Statistics.min(durations);
+      var average = tr.b.Statistics.mean(durations);
+      var min = tr.b.Statistics.min(durations);
 
       var summaryString = ' [';
       summaryString += 'min ' + min.toFixed(2) + 'ms, ';
diff --git a/trace-viewer/trace_viewer/base/unittest/test_case_test.html b/trace-viewer/trace_viewer/base/unittest/test_case_test.html
index 9d9f06c..2c8825a 100644
--- a/trace-viewer/trace_viewer/base/unittest/test_case_test.html
+++ b/trace-viewer/trace_viewer/base/unittest/test_case_test.html
@@ -8,9 +8,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('parseFullyQualifiedName', function() {
-    var p = tv.b.unittest.TestCase.parseFullyQualifiedName('foo.bar');
+    var p = tr.b.unittest.TestCase.parseFullyQualifiedName('foo.bar');
     assert.equal(p.suiteName, 'foo');
     assert.equal(p.testCaseName, 'bar');
   });
diff --git a/trace-viewer/trace_viewer/base/unittest/test_runner.html b/trace-viewer/trace_viewer/base/unittest/test_runner.html
index d284a8a..e72431a 100644
--- a/trace-viewer/trace_viewer/base/unittest/test_runner.html
+++ b/trace-viewer/trace_viewer/base/unittest/test_runner.html
@@ -8,14 +8,14 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.unittest', function() {
+tr.exportTo('tr.b.unittest', function() {
   var realTvOnAnimationFrameError;
   var realWindowOnError;
   var realWindowHistoryPushState;
 
   function installGlobalTestHooks(runner) {
-    realTvOnAnimationFrameError = tv.b.onAnimationFrameError;
-    tv.b.onAnimationFrameError = function(error) {
+    realTvOnAnimationFrameError = tr.b.onAnimationFrameError;
+    tr.b.onAnimationFrameError = function(error) {
       runner.results.addErrorForCurrentTest(error);
     }
 
@@ -32,12 +32,12 @@
     window.history.pushState = function() {
     };
 
-    tv.b.unittest.addHTMLOutputForCurrentTest = function(element) {
+    tr.b.unittest.addHTMLOutputForCurrentTest = function(element) {
       runner.results.addHTMLOutputForCurrentTest(element);
     }
 
     global.sessionStorage.clear();
-    var e = new Event('tv-unittest-will-run');
+    var e = new Event('tr-unittest-will-run');
     document.head.dispatchEvent(e);
   }
 
@@ -45,13 +45,13 @@
     window.onerror = realWindowOnError;
     realWindowOnError = undefined;
 
-    tv.b.onAnimationFrameError = realTvOnAnimationFrameError;
+    tr.b.onAnimationFrameError = realTvOnAnimationFrameError;
     realTvOnAnimationFrameError = undefined;
 
     window.history.pushState = realWindowHistoryPushState;
     realWindowHistoryPushState = undefined;
 
-    tv.b.unittest.addHTMLOutputForCurrentTest = undefined;
+    tr.b.unittest.addHTMLOutputForCurrentTest = undefined;
   }
 
 
@@ -108,7 +108,7 @@
       if (this.runOneTestCaseScheduled_)
         return;
       this.runOneTestCaseScheduled_ = true;
-      tv.b.requestIdleCallback(this.runOneTestCase_, this);
+      tr.b.requestIdleCallback(this.runOneTestCase_, this);
     },
 
     runOneTestCase_: function() {
diff --git a/trace-viewer/trace_viewer/base/unittest/test_suite.html b/trace-viewer/trace_viewer/base/unittest/test_suite.html
index 01995d0..915eff1 100644
--- a/trace-viewer/trace_viewer/base/unittest/test_suite.html
+++ b/trace-viewer/trace_viewer/base/unittest/test_suite.html
@@ -11,14 +11,14 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.unittest', function() {
-  var TestCase = tv.b.unittest.TestCase;
-  var PerfTestCase = tv.b.unittest.PerfTestCase;
+tr.exportTo('tr.b.unittest', function() {
+  var TestCase = tr.b.unittest.TestCase;
+  var PerfTestCase = tr.b.unittest.PerfTestCase;
 
-  var TestTypes = tv.b.unittest.TestTypes;
+  var TestTypes = tr.b.unittest.TestTypes;
 
   function TestSuite(name, suiteConstructor) {
-    this.guid = tv.b.GUID.allocate();
+    this.guid = tr.b.GUID.allocate();
     this.name_ = name;
     this.tests_ = [];
     this.testNames_ = {}; // For dupe checking.
diff --git a/trace-viewer/trace_viewer/base/unittest/text_test_results.html b/trace-viewer/trace_viewer/base/unittest/text_test_results.html
index f90ed8e..69d38bb 100644
--- a/trace-viewer/trace_viewer/base/unittest/text_test_results.html
+++ b/trace-viewer/trace_viewer/base/unittest/text_test_results.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b.unittest', function() {
+tr.exportTo('tr.b.unittest', function() {
   /**
    * @constructor
    */
@@ -40,7 +40,7 @@
     },
 
     addErrorForCurrentTest: function(error) {
-      var normalizedException = tv.b.normalizeException(error);
+      var normalizedException = tr.b.normalizeException(error);
       this.writeToBuffer('Exception: ' + normalizedException.message + '\n' +
           normalizedException.stack + '\n');
       this.currentTestCaseHadErrors_ = true;
diff --git a/trace-viewer/trace_viewer/base/unittest_test.html b/trace-viewer/trace_viewer/base/unittest_test.html
index 3f8b183..65267e6 100644
--- a/trace-viewer/trace_viewer/base/unittest_test.html
+++ b/trace-viewer/trace_viewer/base/unittest_test.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
 
   test('promise', function() {
@@ -20,7 +20,7 @@
 
   test('async', function() {
     return new Promise(function(resolve) {
-      tv.b.requestAnimationFrame(function() {
+      tr.b.requestAnimationFrame(function() {
         resolve();
       });
     });
diff --git a/trace-viewer/trace_viewer/base/utils.html b/trace-viewer/trace_viewer/base/utils.html
index 7770909..3b82160 100644
--- a/trace-viewer/trace_viewer/base/utils.html
+++ b/trace-viewer/trace_viewer/base/utils.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   /**
    * Adds a {@code getInstance} static method that always return the same
    * instance object.
@@ -71,20 +71,7 @@
       position[1] += node.offsetTop;
       node = node.offsetParent;
     }
-    return tv.b.Rect.fromXYWH(position[0], position[1], size[0], size[1]);
-  }
-
-  function clamp(x, lo, hi) {
-    return Math.min(Math.max(x, lo), hi);
-  }
-
-  function lerp(percentage, lo, hi) {
-    var range = hi - lo;
-    return lo + percentage * range;
-  }
-
-  function deg2rad(deg) {
-    return (Math.PI * deg) / 180.0;
+    return tr.b.Rect.fromXYWH(position[0], position[1], size[0], size[1]);
   }
 
   function scrollIntoViewIfNeeded(el) {
@@ -125,10 +112,6 @@
 
     scrollIntoViewIfNeeded: scrollIntoViewIfNeeded,
 
-    clamp: clamp,
-    lerp: lerp,
-    deg2rad: deg2rad,
-
     getUsingPath: getUsingPath
   };
 });
diff --git a/trace-viewer/trace_viewer/base/utils_test.html b/trace-viewer/trace_viewer/base/utils_test.html
index 6a54a3f..19e9969 100644
--- a/trace-viewer/trace_viewer/base/utils_test.html
+++ b/trace-viewer/trace_viewer/base/utils_test.html
@@ -32,27 +32,19 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var THIS_DOC = document._currentScript.ownerDocument;
 
-  test('clamping', function() {
-    assert.equal(tv.b.clamp(2, 1, 3), 2);
-    assert.equal(tv.b.clamp(1, 1, 3), 1);
-    assert.equal(tv.b.clamp(0, 1, 3), 1);
-    assert.equal(tv.b.clamp(3, 1, 3), 3);
-    assert.equal(tv.b.clamp(4, 1, 3), 3);
-  });
-
   test('getUsingPath', function() {
-    var z = tv.b.getUsingPath('x.y.z', {'x': {'y': {'z': 3}}});
+    var z = tr.b.getUsingPath('x.y.z', {'x': {'y': {'z': 3}}});
     assert.equal(z, 3);
 
-    var w = tv.b.getUsingPath('x.w', {'x': {'y': {'z': 3}}});
+    var w = tr.b.getUsingPath('x.w', {'x': {'y': {'z': 3}}});
     assert.isUndefined(w);
   });
 
   test('instantiateTemplatePolymer', function() {
-    var e = tv.b.instantiateTemplate(
+    var e = tr.b.instantiateTemplate(
                 '#instantiate-template-polymer-test',
                 THIS_DOC);
     assert.equal(e.children.length, 1);
@@ -60,7 +52,7 @@
   });
 
   test('instantiateTemplateMultipleTemplates', function() {
-    var outerElement = tv.b.instantiateTemplate(
+    var outerElement = tr.b.instantiateTemplate(
                            '#multiple-template-test',
                            THIS_DOC);
     assert.equal(outerElement.children.length, 2);
diff --git a/trace-viewer/trace_viewer/base/xhr.html b/trace-viewer/trace_viewer/base/xhr.html
index 8b08eef..4ab1b04 100644
--- a/trace-viewer/trace_viewer/base/xhr.html
+++ b/trace-viewer/trace_viewer/base/xhr.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.b', function() {
+tr.exportTo('tr.b', function() {
   var THIS_DOC = document._currentScript.ownerDocument;
 
   function get(url, async) {
@@ -60,4 +60,4 @@
     getSync: getSync
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/build/check_gn.py b/trace-viewer/trace_viewer/build/check_gn.py
deleted file mode 100644
index 4e2d891..0000000
--- a/trace-viewer/trace_viewer/build/check_gn.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# 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.
-
-import os
-import re
-
-from trace_viewer.build import check_common
-
-
-GN_FILE = "BUILD.gn"
-
-
-def ItemToFilename(item):
-  assert item[0] == '"', "GN files use double-quotes, gyp uses single quotes"
-  assert item[-1] == '"', "GN files use double-quotes, gyp uses single quotes"
-  return item[1:-1]
-
-
-def GnCheck():
-  f = open(GN_FILE, 'r')
-  gn = f.read()
-  f.close()
-
-  listed_files = []
-  error = ""
-  for group in check_common.FILE_GROUPS:
-    expr = '%s = \[(.+?)\]\n' % group
-    m = re.search(expr, gn, re.DOTALL)
-    if not m:
-      raise Exception('%s is malformed' % GN_FILE)
-    g = m.group(1).strip()
-    items = g.split(',')
-    filenames = [ItemToFilename(item.strip()) for item in items
-                 if len(item) > 0]
-
-    error += check_common.CheckListedFilesSorted(GN_FILE, group, filenames)
-    listed_files.extend(map(os.path.normpath, filenames))
-
-  return error + check_common.CheckCommon(GN_FILE, listed_files)
-
-if __name__ == '__main__':
-  print GnCheck()
diff --git a/trace-viewer/trace_viewer/build/check_gyp.py b/trace-viewer/trace_viewer/build/check_gyp.py
deleted file mode 100644
index 2373543..0000000
--- a/trace-viewer/trace_viewer/build/check_gyp.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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.
-
-import os
-
-from trace_viewer.build import check_common
-
-GYP_FILE = "trace_viewer.gyp"
-
-def GypCheck():
-  f = open(GYP_FILE, 'r')
-  gyp = f.read()
-  f.close()
-
-  data = eval(gyp)
-  listed_files = []
-  error = ""
-  for group in check_common.FILE_GROUPS:
-    filenames = map(os.path.normpath, data["variables"][group])
-    error += check_common.CheckListedFilesSorted(GYP_FILE, group, filenames)
-    listed_files.extend(filenames)
-
-  return error + check_common.CheckCommon(GYP_FILE, listed_files)
-
-if __name__ == '__main__':
-  print GypCheck()
diff --git a/trace-viewer/trace_viewer/build/check_gypi.py b/trace-viewer/trace_viewer/build/check_gypi.py
new file mode 100644
index 0000000..d55051b
--- /dev/null
+++ b/trace-viewer/trace_viewer/build/check_gypi.py
@@ -0,0 +1,27 @@
+# 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.
+
+import os
+
+from trace_viewer.build import check_common
+
+GYPI_FILE = 'trace_viewer.gypi'
+
+def GypiCheck():
+  f = open(GYPI_FILE, 'r')
+  gyp = f.read()
+  f.close()
+
+  data = eval(gyp)
+  listed_files = []
+  error = ''
+  for group in check_common.FILE_GROUPS:
+    filenames = map(os.path.normpath, data['variables'][group])
+    error += check_common.CheckListedFilesSorted(GYPI_FILE, group, filenames)
+    listed_files.extend(filenames)
+
+  return error + check_common.CheckCommon(GYPI_FILE, listed_files)
+
+if __name__ == '__main__':
+  print GypiCheck()
diff --git a/trace-viewer/trace_viewer/build/update_gyp_and_gn b/trace-viewer/trace_viewer/build/d8_runner
similarity index 71%
rename from trace-viewer/trace_viewer/build/update_gyp_and_gn
rename to trace-viewer/trace_viewer/build/d8_runner
index a7b094c..b8eebc5 100755
--- a/trace-viewer/trace_viewer/build/update_gyp_and_gn
+++ b/trace-viewer/trace_viewer/build/d8_runner
@@ -9,6 +9,5 @@
 if __name__ == '__main__':
   top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
   sys.path.append(top_dir)
-  from trace_viewer import trace_viewer_project
-  from trace_viewer.build import update_gyp_and_gn
-  sys.exit(update_gyp_and_gn.Update())
+  from trace_viewer.build import d8_runner
+  sys.exit(d8_runner.main())
diff --git a/trace-viewer/trace_viewer/build/d8_runner.py b/trace-viewer/trace_viewer/build/d8_runner.py
new file mode 100644
index 0000000..2970ab1
--- /dev/null
+++ b/trace-viewer/trace_viewer/build/d8_runner.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 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.
+
+import argparse
+import os
+import subprocess
+import StringIO
+import sys
+import platform
+
+
+_V8_DIR = os.path.abspath(
+    os.path.join(os.path.dirname(__file__),
+    os.path.pardir, os.path.pardir, 'third_party', 'v8'))
+
+
+def _IsValidJsFile(parser, js_file_arg):
+  if not os.path.exists(js_file_arg):
+    parser.error('The file %s does not exist' % js_file_arg)
+  _, extension = os.path.splitext(js_file_arg)
+  if extension != '.js':
+    parser.error('Input must be a javascript file')
+  return js_file_arg
+
+
+def _GetD8BinaryPathForPlatform():
+  if platform.system() == 'Linux' and platform.machine() == 'x86_64':
+    return os.path.join(_V8_DIR, 'linux', 'x86_64', 'd8')
+  elif platform.system() == 'Darwin' and platform.machine() == 'x86_64':
+    return os.path.join(_V8_DIR, 'mac', 'x86_64', 'd8')
+  else:
+    raise NotImplementedError(
+        'd8 binary for this platform and architecture is not yet supported')
+
+
+def ExcecuteJsFile(js_file_name, js_args):
+  """ Execute the js_file with v8 engine and return the output of the program.
+
+  Args:
+    js_file_name: the string name of the js file to be run.
+    js_args: a list of arguments to passed to the |js_file_name| program.
+  """
+  args = [_GetD8BinaryPathForPlatform()]
+  args.append(js_file_name)
+  if js_args:
+    args += ['--js_arguments'] + js_args
+  sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  out, err = sp.communicate()
+  if sp.returncode != 0:
+    raise RuntimeError(
+        "Exception raised when executing %s with args '%s':\n%s\n%s" %
+        (js_file_name, js_args, out, err))
+  return out
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description='Run javascript file with v8 engine')
+  parser.add_argument('js_file_name', help='input js file', metavar='JS_FILE',
+                      type=lambda f: _IsValidJsFile(parser, f))
+  parser.add_argument('--js_args', help='arguments for the js program',
+                      nargs='+')
+  args = parser.parse_args()
+
+  print ExcecuteJsFile(args.js_file_name, args.js_args)
+  return 0
diff --git a/trace-viewer/trace_viewer/build/d8_unittest.py b/trace-viewer/trace_viewer/build/d8_unittest.py
new file mode 100644
index 0000000..317a6c1
--- /dev/null
+++ b/trace-viewer/trace_viewer/build/d8_unittest.py
@@ -0,0 +1,39 @@
+# Copyright (c) 2014 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.
+
+import os
+import unittest
+
+from trace_viewer.build import d8_runner
+from trace_viewer.build import check_common
+
+
+class CheckCommonUnittTest(unittest.TestCase):
+  def test_filesSortedTest(self):
+    error = check_common.CheckListedFilesSorted('foo.gyp', 'tracing_pdf_files',
+                                                ['/dir/file.pdf',
+                                                 '/dir/another_file.pdf'])
+    expected_error = '''In group tracing_pdf_files from file foo.gyp,\
+ filenames aren't sorted.
+
+First mismatch:
+  /dir/file.pdf
+
+Current listing:
+  /dir/file.pdf
+  /dir/another_file.pdf
+
+Correct listing:
+  /dir/another_file.pdf
+  /dir/file.pdf\n\n'''
+    assert error == expected_error
+
+  def testSimpleJsExecution(self):
+    test_data_dir = os.path.abspath(
+        os.path.join(os.path.dirname(__file__), 'test_data'))
+    js_file_path = os.path.join(test_data_dir, 'print_file_content.js')
+    dummy_test_path = os.path.join(test_data_dir, 'dummy_test_file')
+    output  = d8_runner.ExcecuteJsFile(js_file_path, js_args=[dummy_test_path])
+    self.assertTrue(
+        'This is file contains only data for testing.\n1 2 3 4' in output)
diff --git a/trace-viewer/trace_viewer/build/test_data/dummy_test_file b/trace-viewer/trace_viewer/build/test_data/dummy_test_file
new file mode 100644
index 0000000..2053866
--- /dev/null
+++ b/trace-viewer/trace_viewer/build/test_data/dummy_test_file
@@ -0,0 +1,6 @@
+// Copyright (c) 2015 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.
+
+This is file contains only data for testing.
+1 2 3 4
diff --git a/trace-viewer/trace_viewer/build/test_data/print_file_content.js b/trace-viewer/trace_viewer/build/test_data/print_file_content.js
new file mode 100644
index 0000000..93bb21b
--- /dev/null
+++ b/trace-viewer/trace_viewer/build/test_data/print_file_content.js
@@ -0,0 +1,11 @@
+// Copyright (c) 2015 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.
+
+if (arguments.length != 1) {
+  throw 'arguments must be a single file name';
+}
+
+file_path = arguments[0];
+file_content = read(file_path);
+print('Content of file ' + file_path + ' is ' + file_content);
diff --git a/trace-viewer/trace_viewer/build/trace2html.html b/trace-viewer/trace_viewer/build/trace2html.html
index 0889da9..2ad3a1f 100644
--- a/trace-viewer/trace_viewer/build/trace2html.html
+++ b/trace-viewer/trace_viewer/build/trace2html.html
@@ -31,7 +31,7 @@
 })();
 
 document.addEventListener('DOMContentLoaded', function() {
-  g_timelineViewEl = new tv.TraceViewer();
+  g_timelineViewEl = new tr.TraceViewer();
   g_timelineViewEl.id = 'timeline-view';
   document.body.appendChild(g_timelineViewEl);
 
@@ -45,7 +45,7 @@
     traces.push(atob(text));
   }
 
-  var m = new tv.c.TraceModel();
+  var m = new tr.Model();
   var p = m.importTracesWithProgressDialog(traces, true);
   p.then(
       function() {
@@ -57,8 +57,8 @@
           g_timelineViewEl.timeline.focusElement = g_timelineViewEl;
       },
       function(err) {
-        var overlay = new tv.b.ui.Overlay();
-        overlay.textContent = tv.b.normalizeException(err).message;
+        var overlay = new tr.b.ui.Overlay();
+        overlay.textContent = tr.b.normalizeException(err).message;
         overlay.title = 'Import error';
         overlay.visible = true;
       });
diff --git a/trace-viewer/trace_viewer/build/trace_viewer_dev_server.py b/trace-viewer/trace_viewer/build/trace_viewer_dev_server.py
index a8dffed..5507add 100644
--- a/trace-viewer/trace_viewer/build/trace_viewer_dev_server.py
+++ b/trace-viewer/trace_viewer/build/trace_viewer_dev_server.py
@@ -2,6 +2,7 @@
 # Copyright (c) 2014 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.
+import argparse
 import json
 import os
 import sys
@@ -21,6 +22,8 @@
     for f in filenames:
       if f.startswith('.'):
         continue
+      if f == 'README.md':
+        continue
       full_f = os.path.join(dirpath, f)
       rel_f = os.path.relpath(full_f, basedir)
       data_files.append(rel_f)
@@ -28,10 +31,8 @@
   data_files.sort()
   return data_files
 
-
 def do_GET_json_examples(request):
-  test_data_path = os.path.abspath(os.path.join(_ROOT_PATH, 'test_data'))
-  data_files = getFilesIn(test_data_path)
+  data_files = getFilesIn(request.server.data_dir)
   files_as_json = json.dumps(data_files)
 
   request.send_response(200)
@@ -84,12 +85,21 @@
   request.server.RequestShutdown(exit_code=(0 if 'ALL_PASSED' in msg else 1))
 
 def Main(args):
-  port = 8003
+  parser = argparse.ArgumentParser(description='Run tracing development server')
+  parser.add_argument(
+      '-d', '--data-dir',
+      default=os.path.abspath(os.path.join(_ROOT_PATH, 'test_data')))
+  parser.add_argument('-p', '--port', default=8003, type=int)
+  args = parser.parse_args()
+
   project = trace_viewer_project.TraceViewerProject()
 
-  server = tvcm.DevServer(port=port, project=project)
+  server = tvcm.DevServer(port=args.port, project=project)
+  server.data_dir = os.path.abspath(args.data_dir)
+  project.source_paths.append(server.data_dir)
+
   server.AddPathHandler('/json/examples', do_GET_json_examples)
-  server.AddPathHandler('/tv/json/tests', do_GET_json_tests)
+  server.AddPathHandler('/tr/json/tests', do_GET_json_tests)
   server.AddPathHandler('/json/examples/skp', do_GET_json_examples_skp)
 
   server.AddSourcePathMapping(project.trace_viewer_path)
diff --git a/trace-viewer/trace_viewer/build/update_gyp_and_gn_unittest.py b/trace-viewer/trace_viewer/build/update_gyp_and_gn_unittest.py
deleted file mode 100644
index 25023aa..0000000
--- a/trace-viewer/trace_viewer/build/update_gyp_and_gn_unittest.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright (c) 2014 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.
-import unittest
-import StringIO
-
-from trace_viewer.build.update_gyp_and_gn import BuildFile, GnFile, GypFile
-
-class UpdateGypAndGnTests(unittest.TestCase):
-  def setUp(self):
-    self.file_groups = ['group1', 'group2']
-
-  def test_GnTokenizer(self):
-    content = """useless data
-group1 = [
-"/a/file",
- <there can be useless things here too>
-"/another/file",
-]
-More useless things"""
-    gn_file = GnFile(content, self.file_groups)
-    try:
-      assert len(gn_files._tokens) == 3
-      assert gn_files._tokens[0].id == 'plain'
-      assert gn_files._tokens[0].data == """useless data
-group1 = [
-"""
-      assert gn_files._tokens[1].id == 'group1'
-      assert gn_files._tokens[1].data == """"/a/file",
- <there can be useless things here too>
-"/another/file",
-"""
-      assert gn_files._tokens[2].id == 'plain'
-      assert gn_files._tokens[2].data == """]
-More useless things"""
-    except:
-      pass
-
-  def test_GypTokenizer(self):
-    content = """useless data
-'group1': [
-    <file list goes here>
-    ]
-Note the four spaces bofer the ] above"""
-    gyp_file = GypFile(content, self.file_groups)
-    try:
-      assert len(gyp_files._tokens) == 3
-      assert gyp_files._tokens[0].id == 'plain'
-      assert gyp_files._tokens[0].data == """useless data
-'group1': [
-"""
-      assert gyp_files._tokens[1].id == 'group1'
-      assert gyp_files._tokens[1].data == """    <file list goes here>
-"""
-      assert gyp_files._tokens[2].id == 'plain'
-      assert gyp_files._tokens[2].data == """    ]
-Note the four spaces before the ] above """
-    except:
-      pass
-
-  def test_GnFileListBuilder(self):
-    gn_file = GnFile("", self.file_groups)
-    existing_list_as_string = """    "/four/spaces/indent",
-    "/four/spaces/again",
-"""
-    new_list = ['item1', 'item2', 'item3']
-    try:
-      assert (gn_file._GetReplacementListAsString(existing_list_as_string,
-                                                 new_list)
-              ==
-      """    "item1",\n    "item2",\n    "item3",\n""")
-    except:
-      pass
-
-  def test_GypFileListBuilder(self):
-    gyp_file = GypFile("", self.file_groups)
-    existing_list_as_string = """    '/four/spaces/indent',
-     '/five/spaces/but/only/first/line/matters',
-"""
-    new_list = ['item1', 'item2', 'item3']
-    try:
-      assert (gyp_file._GetReplacementListAsString(existing_list_as_string,
-                                                 new_list)
-              ==
-      """    'item1',\n    'item2',\n    'item3',\n""")
-    except:
-      pass
diff --git a/trace-viewer/trace_viewer/build/update_gyp_and_gn b/trace-viewer/trace_viewer/build/update_gypi
similarity index 67%
copy from trace-viewer/trace_viewer/build/update_gyp_and_gn
copy to trace-viewer/trace_viewer/build/update_gypi
index a7b094c..5e0cdce 100755
--- a/trace-viewer/trace_viewer/build/update_gyp_and_gn
+++ b/trace-viewer/trace_viewer/build/update_gypi
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Copyright (c) 2015 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.
 
@@ -10,5 +10,5 @@
   top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
   sys.path.append(top_dir)
   from trace_viewer import trace_viewer_project
-  from trace_viewer.build import update_gyp_and_gn
-  sys.exit(update_gyp_and_gn.Update())
+  from trace_viewer.build import update_gypi
+  sys.exit(update_gypi.Update())
diff --git a/trace-viewer/trace_viewer/build/update_gyp_and_gn.py b/trace-viewer/trace_viewer/build/update_gypi.py
similarity index 71%
rename from trace-viewer/trace_viewer/build/update_gyp_and_gn.py
rename to trace-viewer/trace_viewer/build/update_gypi.py
index 38c4c7a..a57121b 100644
--- a/trace-viewer/trace_viewer/build/update_gyp_and_gn.py
+++ b/trace-viewer/trace_viewer/build/update_gypi.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Copyright (c) 2015 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.
 
@@ -64,34 +64,7 @@
     raise Exception("Not implemented.")
 
 
-class GnFile(BuildFile):
-  def _ProcessMatch(self, match):
-    min_index = match.start(2)
-    end_index = match.end(2)
-    token = _Token(match.string[min_index:end_index],
-                        id=match.groups()[0])
-    return min_index, end_index, token
-
-  def _TokenRegex(self):
-    # regexp to match the following:
-    # file_group_name = [
-    #   "path/to/one/file.extension",
-    #   "another/file.ex",
-    # ]
-    # In the match,
-    # group 1 is : 'file_group_name'
-    # group 2 is : """  "path/to/one/file.extension",\n  "another/file.ex",\n"""
-    regexp_str = '(%s) = \[\n(.+?)\]\n' % '|'.join(self._file_groups)
-    return re.compile(regexp_str, re.MULTILINE | re.DOTALL)
-
-  def _GetReplacementListAsString(self, existing_list_as_string, filelist):
-    list_entry = existing_list_as_string.splitlines()[0]
-    prefix, entry, suffix = list_entry.split('"')
-    return "".join(['"'.join([prefix, filename, suffix + '\n'])
-                    for filename in filelist])
-
-
-class GypFile(BuildFile):
+class GypiFile(BuildFile):
   def _ProcessMatch(self, match):
     min_index = match.start(2)
     end_index = match.end(2)
@@ -138,18 +111,11 @@
     build_file.Write(f)
 
 
-def UpdateGn():
+def UpdateGypi():
   tvp = trace_viewer_project.TraceViewerProject()
   _UpdateBuildFile(
-      os.path.join(tvp.trace_viewer_path, 'BUILD.gn'), GnFile)
-
-
-def UpdateGyp():
-  tvp = trace_viewer_project.TraceViewerProject()
-  _UpdateBuildFile(
-      os.path.join(tvp.trace_viewer_path, 'trace_viewer.gyp'), GypFile)
+      os.path.join(tvp.trace_viewer_path, 'trace_viewer.gypi'), GypiFile)
 
 
 def Update():
-  UpdateGyp()
-  UpdateGn()
+  UpdateGypi()
diff --git a/trace-viewer/trace_viewer/build/update_gypi_unittest.py b/trace-viewer/trace_viewer/build/update_gypi_unittest.py
new file mode 100644
index 0000000..303de59
--- /dev/null
+++ b/trace-viewer/trace_viewer/build/update_gypi_unittest.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2015 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.
+import unittest
+import StringIO
+
+from trace_viewer.build.update_gypi import BuildFile, GypiFile
+
+class UpdateGypiTests(unittest.TestCase):
+  def setUp(self):
+    self.file_groups = ['group1', 'group2']
+
+  def test_GypiTokenizer(self):
+    content = """useless data
+'group1': [
+    <file list goes here>
+    ]
+Note the four spaces bofer the ] above"""
+    gypi_file = GypiFile(content, self.file_groups)
+    try:
+      assert len(gypi_files._tokens) == 3
+      assert gypi_files._tokens[0].id == 'plain'
+      assert gypi_files._tokens[0].data == """useless data
+'group1': [
+"""
+      assert gypi_files._tokens[1].id == 'group1'
+      assert gypi_files._tokens[1].data == """    <file list goes here>
+"""
+      assert gypi_files._tokens[2].id == 'plain'
+      assert gypi_files._tokens[2].data == """    ]
+Note the four spaces before the ] above """
+    except:
+      pass
+
+  def test_GypiFileListBuilder(self):
+    gypi_file = GypiFile("", self.file_groups)
+    existing_list = """    '/four/spaces/indent',
+     '/five/spaces/but/only/first/line/matters',
+"""
+    new_list = ['item1', 'item2', 'item3']
+    try:
+      assert (gypi_file._GetReplacementListAsString(existing_list, new_list)
+              ==
+      """    'item1',\n    'item2',\n    'item3',\n""")
+    except:
+      pass
diff --git a/trace-viewer/trace_viewer/core/analysis/alert_sub_view.html b/trace-viewer/trace_viewer/core/analysis/alert_sub_view.html
index e4e4342..12244b9 100644
--- a/trace-viewer/trace_viewer/core/analysis/alert_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/alert_sub_view.html
@@ -5,15 +5,15 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/base/base.html">
 <link rel="import" href="/base/ui.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 
-<polymer-element name="tv-c-a-alert-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-alert-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -25,8 +25,8 @@
       align-self: stretch;
     }
     </style>
-    <tracing-analysis-nested-table id="table">
-    </tracing-analysis-nested-table>
+    <tr-b-ui-table id="table">
+    </tr-b-ui-table>
   </template>
   <script>
   'use strict';
@@ -64,7 +64,7 @@
       // Arguments
       for (var argName in alert.args) {
         var argView =
-            document.createElement('tv-c-analysis-generic-object-view');
+            document.createElement('tr-c-a-generic-object-view');
         argView.object = alert.args[argName];
         rows.push({ name: argName, value: argView });
       }
@@ -72,13 +72,13 @@
       // Associated events
       if (alert.associatedEvents.length) {
         alert.associatedEvents.forEach(function(event, i) {
-          var linkEl = document.createElement('tv-c-analysis-link');
+          var linkEl = document.createElement('tr-c-a-analysis-link');
           linkEl.setSelectionAndContent(function() {
-            return new tv.c.Selection(event);
+            return new tr.c.Selection(event);
           }, event.title);
 
           var valueString = '';
-          if (event instanceof tv.c.trace_model.TimedEvent)
+          if (event instanceof tr.model.TimedEvent)
             valueString = 'took ' + event.duration.toFixed(2) + 'ms';
 
           rows.push({
@@ -89,7 +89,7 @@
       }
 
       // Description
-      var descriptionEl = tv.b.ui.createDiv({
+      var descriptionEl = tr.b.ui.createDiv({
           textContent: alert.info.description,
           maxWidth: '300px'
       });
diff --git a/trace-viewer/trace_viewer/core/analysis/alert_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/alert_sub_view_test.html
index 35391c2..8802ff4 100644
--- a/trace-viewer/trace_viewer/core/analysis/alert_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/alert_sub_view_test.html
@@ -9,19 +9,19 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
   test('instantiate', function() {
     var slice = newSliceEx({title: 'b', start: 0, duration: 0.002});
 
-    var ALERT_INFO_1 = new tv.c.trace_model.EventInfo(
+    var ALERT_INFO_1 = new tr.model.EventInfo(
         'Alert 1', 'Critical alert',
         [{
           label: 'Project Page',
@@ -29,17 +29,17 @@
           href: 'https://github.com/google/trace-viewer/'
         }]);
 
-    var alert = new tv.c.trace_model.Alert(ALERT_INFO_1, 5, [slice]);
+    var alert = new tr.model.Alert(ALERT_INFO_1, 5, [slice]);
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(alert);
 
-    var subView = document.createElement('tv-c-a-alert-sub-view');
+    var subView = document.createElement('tr-c-a-alert-sub-view');
     subView.selection = selection;
     this.addHTMLOutput(subView);
 
-    var table = tv.b.findDeepElementMatching(
-        subView, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        subView, 'tr-b-ui-table');
 
     var rows = table.tableRows;
     var columns = table.tableColumns;
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_link.html b/trace-viewer/trace_viewer/core/analysis/analysis_link.html
index 89adbc0..c81dd90 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_link.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_link.html
@@ -5,11 +5,11 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/base/ui.html">
 
-<polymer-element name="tv-c-analysis-link" is="a">
+<polymer-element name="tr-c-a-analysis-link" is="a">
   <template>
     <style>
     :host {
@@ -55,7 +55,7 @@
       if (!this.selection_)
         return;
 
-      var event = new tv.c.RequestSelectionChangeEvent();
+      var event = new tr.c.RequestSelectionChangeEvent();
       if (typeof this.selection_ === 'function')
         event.selection = this.selection_();
       else
@@ -64,4 +64,4 @@
     }
   });
   </script>
-</polymer-element>
\ No newline at end of file
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_link_test.html b/trace-viewer/trace_viewer/core/analysis/analysis_link_test.html
index 7aca7cc..c7feba5 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_link_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_link_test.html
@@ -6,20 +6,20 @@
 -->
 
 <link rel="import" href="/core/analysis/analysis_link.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('testBasic', function() {
-    var link = document.createElement('tv-c-analysis-link');
+    var link = document.createElement('tr-c-a-analysis-link');
 
-    var i10 = new tv.c.trace_model.ObjectInstance(
+    var i10 = new tr.model.ObjectInstance(
     {}, '0x1000', 'cat', 'name', 10);
     var s10 = i10.addSnapshot(10, {foo: 1});
 
-    link.selection = new tv.c.Selection(s10);
+    link.selection = new tr.c.Selection(s10);
     this.addHTMLOutput(link);
 
     var didRSC = false;
@@ -32,14 +32,14 @@
   });
 
   test('testGeneratorVersion', function() {
-    var link = document.createElement('tv-c-analysis-link');
+    var link = document.createElement('tr-c-a-analysis-link');
 
-    var i10 = new tv.c.trace_model.ObjectInstance(
+    var i10 = new tr.model.ObjectInstance(
     {}, '0x1000', 'cat', 'name', 10);
     var s10 = i10.addSnapshot(10, {foo: 1});
 
     function selectionGenerator() {
-      return new tv.c.Selection(s10);
+      return new tr.c.Selection(s10);
     }
     selectionGenerator.userFriendlyName = 'hello world';
     link.selection = selectionGenerator;
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_results.html b/trace-viewer/trace_viewer/core/analysis/analysis_results.html
index c604824..d22f0ae 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_results.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_results.html
@@ -7,15 +7,15 @@
 <link rel="stylesheet" href="/core/analysis/analysis_results.css">
 
 <link rel="import" href="/base/ui.html">
-<link rel="import" href="/core/analysis/util.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';
 
-tv.exportTo('tv.c.analysis', function() {
-  var AnalysisResults = tv.b.ui.define('div');
+tr.exportTo('tr.c.analysis', function() {
+  var AnalysisResults = tr.b.ui.define('div');
 
   AnalysisResults.prototype = {
     __proto__: HTMLDivElement.prototype,
@@ -34,7 +34,7 @@
 
     createSelectionChangingLink: function(text, selectionGenerator,
                                           opt_tooltip) {
-      var el = this.ownerDocument.createElement('tv-c-analysis-link');
+      var el = this.ownerDocument.createElement('tr-c-a-analysis-link');
       function wrap() {
         return selectionGenerator();
       }
@@ -198,7 +198,7 @@
       this.appendTableCell_(table, row, 0, label);
       if (opt_value !== undefined) {
         var objectView =
-            document.createElement('tv-c-analysis-generic-object-view');
+            document.createElement('tr-c-a-generic-object-view');
         objectView.object = opt_value;
         objectView.classList.add('analysis-table-col-1');
         objectView.style.display = 'table-cell';
@@ -221,7 +221,7 @@
         var row = this.appendBodyRow(table);
       this.appendTableCell_(table, row, 0, label);
       this.appendTableCell_(
-          table, row, 1, tv.c.analysis.tsString(time), opt_warning);
+          table, row, 1, tr.b.units.tsString(time), opt_warning);
     },
 
     /**
@@ -246,26 +246,26 @@
 
         if (opt_selectionGenerator) {
           var labelEl = this.appendTableCell(table, row,
-                                             tv.c.analysis.tsString(start));
+                                             tr.b.units.tsString(start));
           labelEl.textContent = '';
           labelEl.appendChild(this.createSelectionChangingLink(
-                                      tv.c.analysis.tsString(start),
+                                      tr.b.units.tsString(start),
                                       opt_selectionGenerator, ''));
         } else {
-          this.appendTableCell(table, row, tv.c.analysis.tsString(start));
+          this.appendTableCell(table, row, tr.b.units.tsString(start));
         }
       }
       if (duration !== null)
-        this.appendTableCell(table, row, tv.c.analysis.tsString(duration));
+        this.appendTableCell(table, row, tr.b.units.tsString(duration));
 
       if (opt_cpuDuration)
         this.appendTableCell(table, row,
                              opt_cpuDuration != '' ?
-                             tv.c.analysis.tsString(opt_cpuDuration) :
+                             tr.b.units.tsString(opt_cpuDuration) :
                              '');
 
       if (selfTime !== null)
-        this.appendTableCell(table, row, tv.c.analysis.tsString(selfTime));
+        this.appendTableCell(table, row, tr.b.units.tsString(selfTime));
 
       var argsCell = this.appendTableCell(table, row, '');
       var n = 0;
@@ -277,7 +277,7 @@
         for (var argName in args) {
           var argVal = args[argName];
           var objectView =
-              document.createElement('tv-c-analysis-generic-object-view');
+              document.createElement('tr-c-a-generic-object-view');
           objectView.object = argVal;
           var argsRow = this.appendElement_(
               this.appendElement_(argsCell, 'table'), 'tr');
@@ -304,28 +304,29 @@
 
       var tooltip = undefined;
       if (opt_statistics) {
+        var stddevRounded = Math.round(opt_statistics.avg_stddev * 1000) / 1000;
+
         tooltip = 'Min Duration:\u0009' +
-                  tv.c.analysis.tsString(opt_statistics.min) +
-                  ' ms \u000DMax Duration:\u0009' +
-                  tv.c.analysis.tsString(opt_statistics.max) +
-                  ' ms \u000DAvg Duration:\u0009' +
-                  tv.c.analysis.tsString(opt_statistics.avg) +
-                  ' ms (\u03C3 = ' +
-                  tv.c.analysis.tsRound(opt_statistics.avg_stddev) + ')';
+                  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' +
-              tv.c.analysis.tsString(opt_statistics.start);
+              tr.b.units.tsString(opt_statistics.start);
         }
         if (opt_statistics.end) {
           tooltip += '\u000DEnd Time:\u0009' +
-              tv.c.analysis.tsString(opt_statistics.end);
+              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' +
-              tv.c.analysis.tsRound(opt_statistics.frequency) +
-              ' occurrences/s (\u03C3 = ' +
-              tv.c.analysis.tsRound(opt_statistics.frequency_stddev) + ')';
+              fR + ' occurrences/s (\u03C3 = ' + fSR + ')';
         }
       }
 
@@ -356,7 +357,7 @@
                 '[' + opt_duration.join(', ') + ']', tooltip);
           } else {
             this.appendTableCellWithTooltip_(table, row, cellNum,
-                tv.c.analysis.tsString(opt_duration), tooltip);
+                tr.b.units.tsString(opt_duration), tooltip);
           }
         } else {
           this.appendTableCell_(table, row, cellNum, '');
@@ -367,7 +368,7 @@
       if (opt_cpuDuration !== null) {
         if (opt_cpuDuration != '') {
           this.appendTableCellWithTooltip_(table, row, cellNum,
-              tv.c.analysis.tsString(opt_cpuDuration), tooltip);
+              tr.b.units.tsString(opt_cpuDuration), tooltip);
         } else {
           this.appendTableCell_(table, row, cellNum, '');
         }
@@ -377,7 +378,7 @@
       if (opt_selfTime !== null) {
         if (opt_selfTime) {
           this.appendTableCellWithTooltip_(table, row, cellNum,
-              tv.c.analysis.tsString(opt_selfTime), tooltip);
+              tr.b.units.tsString(opt_selfTime), tooltip);
         } else {
           this.appendTableCell_(table, row, cellNum, '');
         }
@@ -387,7 +388,7 @@
       if (opt_cpuSelfTime !== null) {
         if (opt_cpuSelfTime) {
           this.appendTableCellWithTooltip_(table, row, cellNum,
-              tv.c.analysis.tsString(opt_cpuSelfTime), tooltip);
+              tr.b.units.tsString(opt_cpuSelfTime), tooltip);
         } else {
           this.appendTableCell_(table, row, cellNum, '');
         }
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_results_test.html b/trace-viewer/trace_viewer/core/analysis/analysis_results_test.html
index 4371a2d..bdecfd0 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_results_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_results_test.html
@@ -12,12 +12,12 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('selectionChangingLink', function() {
-    var r = tv.c.analysis.AnalysisResults();
+    var r = tr.c.analysis.AnalysisResults();
     var track = {};
     var linkEl = r.createSelectionChangingLink('hello', function() {
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       selection.push({guid: 1});
       return selection;
     });
@@ -30,8 +30,8 @@
   });
 
   test('displayValuesInInfoRow', function() {
-    var r = new tv.c.analysis.AnalysisResults();
-    var table = new tv.c.analysis.StubAnalysisTable();
+    var r = new tr.c.analysis.AnalysisResults();
+    var table = new tr.c.analysis.StubAnalysisTable();
     var node;
     var sectionNode;
     assert.equal(table.nodeCount, 0);
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_sub_view.html b/trace-viewer/trace_viewer/core/analysis/analysis_sub_view.html
index a5a4c9f..8e27d1b 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_sub_view.html
@@ -10,8 +10,7 @@
 <!--
 @fileoverview Polymer element for various analysis sub-views.
 -->
-<polymer-element name="tracing-analysis-sub-view"
-    constructor="TracingAnalysisSubView">
+<polymer-element name="tr-c-a-sub-view">
   <script>
   'use strict';
   Polymer({
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/analysis_sub_view_test.html
index 2aaa0bc..c7c0f56 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_sub_view_test.html
@@ -11,12 +11,12 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('subViewThrowsNotImplementedErrors', function() {
-    var subView = new TracingAnalysisSubView();
+    var subView = document.createElement('tr-c-a-sub-view');
 
     assert.throw(function() {
-      subView.selection = new tv.c.Selection();
+      subView.selection = new tr.c.Selection();
     }, 'Not implemented!');
 
     assert.throw(function() {
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_view.html b/trace-viewer/trace_viewer/core/analysis/analysis_view.html
index 4be3d9d..e9f5c02 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_view.html
@@ -62,7 +62,7 @@
 @fileoverview A component used to display an analysis of a selection,
 using custom elements specialized for different event types.
 -->
-<polymer-element name="tv-c-a-analysis-view">
+<polymer-element name="tr-c-a-analysis-view">
   <template>
     <style>
       :host {
@@ -86,7 +86,7 @@
   <script>
   'use strict';
   (function() {
-    var EventRegistry = tv.c.trace_model.EventRegistry;
+    var EventRegistry = tr.model.EventRegistry;
 
     Polymer({
       ready: function() {
@@ -98,7 +98,7 @@
         this.onSelectedTabChange_ = this.onSelectedTabChange_.bind(this);
         this.onSelectionChanged_ = this.onSelectionChanged_.bind(this);
 
-        this.lastSeenSelection_ = new tv.c.Selection();
+        this.lastSeenSelection_ = new tr.c.Selection();
       },
 
       set tallMode(value) {
@@ -169,7 +169,7 @@
 
         var eventsByBaseTypeName = selection.getEventsOrganizedByBaseType(true);
 
-        var numBaseTypesToAnalyze = tv.b.dictionaryLength(eventsByBaseTypeName);
+        var numBaseTypesToAnalyze = tr.b.dictionaryLength(eventsByBaseTypeName);
         for (var eventTypeName in eventsByBaseTypeName) {
           var subSelection = eventsByBaseTypeName[eventTypeName];
           var subView = this.createSubViewForSelection_(
@@ -189,7 +189,7 @@
 
         // If that fails, look for a tab with that typeName.
         if (!tab && lastSelectedTabTypeName) {
-          var tab = tv.b.findFirstInArray(
+          var tab = tr.b.findFirstInArray(
               this.tabView_.children, function(tab) {
             return tab._eventTypeName === lastSelectedTabTypeName;
           });
@@ -217,7 +217,7 @@
         else
           tagName = eventTypeInfo.metadata.multiViewElementName;
 
-        if (!tv.b.getPolymerElementNamed(tagName))
+        if (!tr.b.getPolymerElementNamed(tagName))
           throw new Error('Element not registered: ' + tagName);
 
         // Create.
diff --git a/trace-viewer/trace_viewer/core/analysis/analysis_view_test.html b/trace-viewer/trace_viewer/core/analysis/analysis_view_test.html
index 8bd0ca8..18e7de3 100644
--- a/trace-viewer/trace_viewer/core/analysis/analysis_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/analysis_view_test.html
@@ -7,12 +7,12 @@
 
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/selection.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view.html b/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view.html
index 6cb5b56..671e728 100644
--- a/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view.html
@@ -5,17 +5,17 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/analysis_results.html">
-<link rel="import" href="/core/trace_model/counter_sample.html">
+<link rel="import" href="/model/counter_sample.html">
 
-<polymer-element name="tv-c-counter-sample-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-counter-sample-sub-view"
+    extends="tr-c-a-sub-view">
   <script>
   'use strict';
   (function() {
-    var CounterSample = tv.c.trace_model.CounterSample;
+    var CounterSample = tr.model.CounterSample;
 
     Polymer({
       created: function() {
@@ -27,7 +27,7 @@
       },
 
       set selection(selection) {
-        var results = new tv.c.analysis.AnalysisResults();
+        var results = new tr.c.analysis.AnalysisResults();
         this.appendChild(results);
         this.analyzeCounterSamples_(results, selection);
       },
@@ -98,4 +98,4 @@
     });
   })();
   </script>
-</polymer-element>
\ No newline at end of file
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view_test.html
index 78de05e..ea829ff 100644
--- a/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/counter_sample_sub_view_test.html
@@ -9,17 +9,17 @@
 <link rel="import" href="/core/analysis/stub_analysis_results.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Counter = tv.c.trace_model.Counter;
-  var CounterSeries = tv.c.trace_model.CounterSeries;
+tr.b.unittest.testSuite(function() {
+  var Counter = tr.model.Counter;
+  var CounterSeries = tr.model.CounterSeries;
 
-  var Selection = tv.c.Selection;
-  var StubAnalysisResults = tv.c.analysis.StubAnalysisResults;
+  var Selection = tr.c.Selection;
+  var StubAnalysisResults = tr.c.analysis.StubAnalysisResults;
 
   function createSeries(ctr) {
     var allocatedSeries = new CounterSeries('bytesallocated', 0);
@@ -52,7 +52,7 @@
   test('instantiate_singleCounterWithTwoSeries', function() {
     var selection = createSelectionWithTwoSeriesSingleCounter();
 
-    var analysisEl = document.createElement('tv-c-counter-sample-sub-view');
+    var analysisEl = document.createElement('tr-c-a-counter-sample-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
   });
@@ -79,7 +79,7 @@
   test('instantiate_twoCountersWithTwoSeries', function() {
     var selection = createSelectionWithTwoSeriesTwoCounters();
 
-    var analysisEl = document.createElement('tv-c-counter-sample-sub-view');
+    var analysisEl = document.createElement('tr-c-a-counter-sample-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
   });
@@ -96,7 +96,7 @@
     var t1track = {};
     selection.push(ctr.getSeries(0).samples[1]);
 
-    var view = document.createElement('tv-c-counter-sample-sub-view');
+    var view = document.createElement('tr-c-a-counter-sample-sub-view');
     var results = new StubAnalysisResults();
     view.analyzeCounterSamples_(results, selection);
 
@@ -159,7 +159,7 @@
   test('analyzeSelectionWithComplexSeriesTwoCounters', function() {
     var selection = createSelectionWithTwoCountersDiffSeriesDiffEvents();
 
-    var view = document.createElement('tv-c-counter-sample-sub-view');
+    var view = document.createElement('tr-c-a-counter-sample-sub-view');
     var results = new StubAnalysisResults();
     view.analyzeCounterSamples_(results, selection);
 
diff --git a/trace-viewer/trace_viewer/core/analysis/flow_classifier.html b/trace-viewer/trace_viewer/core/analysis/flow_classifier.html
index d1aa061..098d225 100644
--- a/trace-viewer/trace_viewer/core/analysis/flow_classifier.html
+++ b/trace-viewer/trace_viewer/core/analysis/flow_classifier.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.analysis', function() {
+tr.exportTo('tr.c.analysis', function() {
   var FLOW_IN = 0x1;
   var FLOW_OUT = 0x2;
   var FLOW_IN_OUT = FLOW_IN | FLOW_OUT;
@@ -46,12 +46,12 @@
       return event;
     },
 
-    get hasEvents() {
+    hasEvents: function() {
       return this.numEvents_ > 0;
     },
 
     get inFlowEvents() {
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       for (var guid in this.eventsByGUID_) {
         var fs = this.eventsByGUID_[guid];
         if (fs.state === FLOW_IN)
@@ -61,7 +61,7 @@
     },
 
     get outFlowEvents() {
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       for (var guid in this.eventsByGUID_) {
         var fs = this.eventsByGUID_[guid];
         if (fs.state === FLOW_OUT)
@@ -71,7 +71,7 @@
     },
 
     get internalFlowEvents() {
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       for (var guid in this.eventsByGUID_) {
         var fs = this.eventsByGUID_[guid];
         if (fs.state === FLOW_IN_OUT)
diff --git a/trace-viewer/trace_viewer/core/analysis/flow_classifier_test.html b/trace-viewer/trace_viewer/core/analysis/flow_classifier_test.html
index e3ef056..fcf206c 100644
--- a/trace-viewer/trace_viewer/core/analysis/flow_classifier_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/flow_classifier_test.html
@@ -9,13 +9,13 @@
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/base/iteration_helpers.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newFlowEventEx = tv.c.test_utils.newFlowEventEx;
+tr.b.unittest.testSuite(function() {
+  var newFlowEventEx = tr.c.test_utils.newFlowEventEx;
 
   test('basic', function() {
     var a = newFlowEventEx({
@@ -27,7 +27,7 @@
     var d = newFlowEventEx({
         'title': 'd', start: 30, end: 35 });
 
-    var fc = new tv.c.analysis.FlowClassifier();
+    var fc = new tr.c.analysis.FlowClassifier();
     fc.addInFlow(a);
 
     fc.addInFlow(b);
@@ -39,7 +39,7 @@
     fc.addOutFlow(d);
 
     function asSortedArray(selection) {
-      var events = tv.b.asArray(selection);
+      var events = tr.b.asArray(selection);
       events.sort(function(a, b) {
         return a.guid - b.guid;
       });
diff --git a/trace-viewer/trace_viewer/core/analysis/generic_object_view.html b/trace-viewer/trace_viewer/core/analysis/generic_object_view.html
index fb6778b..0f9cb08 100644
--- a/trace-viewer/trace_viewer/core/analysis/generic_object_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/generic_object_view.html
@@ -6,11 +6,17 @@
 -->
 
 <link rel="import" href="/core/analysis/analysis_link.html">
-<link rel="import" href="/base/time.html">
+<link rel="import" href="/base/units/time_duration.html">
+<link rel="import" href="/base/units/time_stamp.html">
+<link rel="import" href="/base/units/size_in_bytes.html">
+<link rel="import" href="/base/units/time_duration_span.html">
+<link rel="import" href="/base/units/time_stamp_span.html">
+<link rel="import" href="/base/units/size_in_bytes_span.html">
 <link rel="import" href="/base/utils.html">
 <link rel="import" href="/base/ui.html">
+<link rel="import" href="/base/ui/table.html">
 
-<polymer-element name="tv-c-analysis-generic-object-view"
+<polymer-element name="tr-c-a-generic-object-view"
     is="HTMLUnknownElement">
   <template>
     <style>
@@ -139,34 +145,41 @@
         }
       }
 
-      if (object instanceof tv.c.trace_model.ObjectSnapshot) {
-        var link = document.createElement('tv-c-analysis-link');
-        link.selection = new tv.c.Selection(object);
+      if (object instanceof tr.model.ObjectSnapshot) {
+        var link = document.createElement('tr-c-a-analysis-link');
+        link.selection = new tr.c.Selection(object);
         this.appendElementWithLabel_(label, indent, link, suffix);
         return;
       }
 
-      if (object instanceof tv.c.trace_model.ObjectInstance) {
-        var link = document.createElement('tv-c-analysis-link');
-        link.selection = new tv.c.Selection(object);
+      if (object instanceof tr.model.ObjectInstance) {
+        var link = document.createElement('tr-c-a-analysis-link');
+        link.selection = new tr.c.Selection(object);
         this.appendElementWithLabel_(label, indent, link, suffix);
         return;
       }
 
-      if (object instanceof tv.b.Rect) {
+      if (object instanceof tr.b.Rect) {
         this.appendSimpleText_(label, indent, object.toString(), suffix);
         return;
       }
 
-      if (object instanceof tv.b.TimeDuration) {
-        var el = this.ownerDocument.createElement('tv-c-a-time-span');
+      if (object instanceof tr.b.units.SizeInBytes) {
+        var el = this.ownerDocument.createElement('tr-b-u-size-in-bytes-span');
+        el.numBytes = object.numBytes;
+        this.appendElementWithLabel_(label, indent, el, suffix);
+        return;
+      }
+
+      if (object instanceof tr.b.units.TimeDuration) {
+        var el = this.ownerDocument.createElement('tr-b-u-time-duration-span');
         el.duration = object.duration;
         this.appendElementWithLabel_(label, indent, el, suffix);
         return;
       }
 
-      if (object instanceof tv.b.TimeStamp) {
-        var el = this.ownerDocument.createElement('tv-c-a-time-stamp');
+      if (object instanceof tr.b.units.TimeStamp) {
+        var el = this.ownerDocument.createElement('tr-b-u-time-stamp-span');
         el.timestamp = object.timestamp;
         this.appendElementWithLabel_(label, indent, el, suffix);
         return;
@@ -190,28 +203,17 @@
       }
 
       if (isTable(object)) {
-        var table = document.createElement('table');
-        var tr = document.createElement('tr');
-        table.appendChild(tr);
+        var table = document.createElement('tr-b-ui-table');
         var columns = [];
-        for (var colName in object[0]) {
-          columns.push(colName);
-          var th = document.createElement('th');
-          th.textContent = colName;
-          tr.appendChild(th);
-        }
-        object.forEach(function(row) {
-          var tr = document.createElement('tr');
-          table.appendChild(tr);
-          columns.forEach(function(colName) {
-            var cell = row[colName];
-            var td = document.createElement('td');
-            td.textContent = cell;
-            td.style.textAlign = isNaN(parseFloat(cell)) ? 'left' : 'right';
-            tr.appendChild(td);
-          });
+        tr.b.iterItems(object[0], function(colName) {
+          columns.push({title: colName, value: function(row) {
+            return row[colName];
+          }});
         });
+        table.tableColumns = columns;
+        table.tableRows = object;
         this.appendElementWithLabel_(label, indent, table, suffix);
+        table.rebuild();
         return;
       }
 
@@ -232,7 +234,7 @@
 
     appendElementsForObject_: function(
         label, object, indent, depth, maxDepth, suffix) {
-      var keys = tv.b.dictionaryKeys(object);
+      var keys = tr.b.dictionaryKeys(object);
       if (keys.length == 0) {
         this.appendSimpleText_(label, indent, '{}', suffix);
         return;
@@ -284,7 +286,7 @@
   </script>
 </polymer-element>
 
-<polymer-element name="tv-c-analysis-generic-object-view-with-label"
+<polymer-element name="tr-c-a-generic-object-view-with-label"
     is="HTMLUnknownElement">
   <template>
     <style>
@@ -301,7 +303,7 @@
     ready: function() {
       this.labelEl_ = document.createElement('div');
       this.genericObjectView_ =
-          document.createElement('tv-c-analysis-generic-object-view');
+          document.createElement('tr-c-a-generic-object-view');
       this.shadowRoot.appendChild(this.labelEl_);
       this.shadowRoot.appendChild(this.genericObjectView_);
     },
diff --git a/trace-viewer/trace_viewer/core/analysis/generic_object_view_test.html b/trace-viewer/trace_viewer/core/analysis/generic_object_view_test.html
index b4fe5df..90677aa 100644
--- a/trace-viewer/trace_viewer/core/analysis/generic_object_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/generic_object_view_test.html
@@ -7,39 +7,39 @@
 
 <link rel="import" href="/base/deep_utils.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('undefinedValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = undefined;
     assert.equal(view.$.content.textContent, 'undefined');
   });
 
   test('nullValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = null;
     assert.equal(view.$.content.textContent, 'null');
   });
 
   test('stringValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = 'string value';
     assert.equal(view.$.content.textContent, '"string value"');
   });
 
   test('multiLineStringValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = 'i am a\n  string value\ni have\n  various indents';
     this.addHTMLOutput(view);
     var c = view.$.content;
   });
 
   test('multiLineStringValueInsideObject', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = {key: 'i am a\n  string value\ni have\n  various indents',
                    value: 'simple'};
     this.addHTMLOutput(view);
@@ -48,120 +48,118 @@
   });
 
   test('jsonObjectStringValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = '{"x": 1}';
     assert.equal(view.$.content.children.length, 1);
     assert.equal(view.$.content.children[0].children.length, 4);
   });
 
   test('jsonArrayStringValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = '[1,2,3]';
     assert.equal(view.$.content.children.length, 3);
   });
 
   test('booleanValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = false;
     assert.equal(view.$.content.textContent, 'false');
   });
 
   test('numberValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = 3.14159;
     assert.equal(view.$.content.textContent, '3.14159');
   });
 
   test('objectSnapshotValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
 
-    var i10 = new tv.c.trace_model.ObjectInstance(
+    var i10 = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'name', 10);
     var s10 = i10.addSnapshot(10, {foo: 1});
 
     view.object = s10;
     this.addHTMLOutput(view);
     assert.strictEqual(view.$.content.children[0].dataElement.tagName,
-        'TV-C-ANALYSIS-LINK');
+        'TR-C-A-ANALYSIS-LINK');
   });
 
   test('objectInstanceValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
 
-    var i10 = new tv.c.trace_model.ObjectInstance(
+    var i10 = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'name', 10);
     var s10 = i10.addSnapshot(10, {foo: 1});
 
     view.object = i10;
     assert.strictEqual(view.$.content.children[0].dataElement.tagName,
-        'TV-C-ANALYSIS-LINK');
+        'TR-C-A-ANALYSIS-LINK');
   });
 
   test('instantiate_emptyArrayValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [];
     this.addHTMLOutput(view);
   });
 
   test('instantiate_twoValueArrayValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [1, 2];
     this.addHTMLOutput(view);
   });
 
   test('instantiate_twoValueBArrayValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [1, {x: 1}];
     this.addHTMLOutput(view);
   });
 
   test('instantiate_arrayValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [1, 2, 'three'];
     this.addHTMLOutput(view);
   });
 
   test('instantiate_arrayWithSimpleObjectValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [{simple: 'object'}];
     this.addHTMLOutput(view);
   });
 
   test('instantiate_arrayWithComplexObjectValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [{col0: 'object', col1: 0},
                    {col2: 'Object', col3: 1}];
     this.addHTMLOutput(view);
-    assert.equal(undefined, tv.b.findDeepElementMatching(
+    assert.equal(undefined, tr.b.findDeepElementMatching(
       view.$.content, 'table'));
   });
 
   test('instantiate_arrayWithDeepObjectValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [{key: {deep: 'object values make isTable() return false'}}];
     this.addHTMLOutput(view);
-    assert.equal(undefined, tv.b.findDeepElementMatching(
+    assert.equal(undefined, tr.b.findDeepElementMatching(
       view.$.content, 'table'));
   });
 
   test('jsonTableValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = [{col0: 'object', col1: 0}, {col0: 'Object', col1: 1}];
     this.addHTMLOutput(view);
-    var table = tv.b.findDeepElementMatching(view.$.content, 'table');
-    assert.equal(1 + view.object.length, table.rows.length);
-    assert.equal(2, table.rows[0].children.length);
-    assert.equal('col0', table.rows[0].children[0].textContent);
-    assert.equal('col1', table.rows[0].children[1].textContent);
-    view.object.forEach(function(row, rowIndex) {
-      assert.equal(2, table.rows[1 + rowIndex].children.length);
-      assert.equal(row.col0, table.rows[1 + rowIndex].children[0].textContent);
-      assert.equal(row.col1, table.rows[1 + rowIndex].children[1].textContent);
-    });
+    var table = tr.b.findDeepElementMatching(
+        view.$.content, 'tr-b-ui-table');
+    assert.equal('col0', table.tableColumns[0].title);
+    assert.equal('col1', table.tableColumns[1].title);
+    assert.equal('object', table.tableColumns[0].value(table.tableRows[0]));
+    assert.equal('Object', table.tableColumns[0].value(table.tableRows[1]));
+    assert.equal(0, table.tableColumns[1].value(table.tableRows[0]));
+    assert.equal(1, table.tableColumns[1].value(table.tableRows[1]));
   });
 
   test('instantiate_objectValue', function() {
-    var view = document.createElement('tv-c-analysis-generic-object-view');
+    var view = document.createElement('tr-c-a-generic-object-view');
     view.object = {
       'entry_one': 'entry_one_value',
       'entry_two': 2,
@@ -169,5 +167,28 @@
     };
     this.addHTMLOutput(view);
   });
+
+  test('timeDurationValue', function() {
+    var view = document.createElement('tr-c-a-generic-object-view');
+    view.object = new tr.b.units.TimeDuration(3);
+    assert.isDefined(tr.b.findDeepElementMatching(
+      view.$.content, 'tr-b-u-time-duration-span'));
+  });
+
+  test('timeStampValue', function() {
+    var view = document.createElement('tr-c-a-generic-object-view');
+    view.object = new tr.b.units.TimeStamp(3);
+    assert.isDefined(tr.b.findDeepElementMatching(
+      view.$.content, 'tr-b-u-time-stamp-span'));
+  });
+
+  test('sizeInBytesValue', function() {
+    var view = document.createElement('tr-c-a-generic-object-view');
+    view.object = new tr.b.units.SizeInBytes(3);
+    assert.isDefined(tr.b.findDeepElementMatching(
+      view.$.content, 'tr-b-u-size-in-bytes-span'));
+  });
+
+
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane.html
index 4c805ad..e8064cb 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane.html
@@ -6,9 +6,9 @@
 -->
 
 <link rel="import" href="/core/analysis/memory_dump_sub_view_util.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 
-<polymer-element name="tv-c-memory-dump-allocator-details-pane">
+<polymer-element name="tr-c-a-memory-dump-allocator-details-pane">
   <template>
     <style>
       :host {
@@ -47,87 +47,116 @@
   <script>
   'use strict';
 
-  Polymer({
-    // TODO(petrcermak): Consider sharing more code between
-    // tv-c-memory-dump-overview-pane and
-    // tv-c-memory-dump-allocator-details-pane (e.g. by defining a common base
-    // class tv-c-memory-dump-pane).
-
-    created: function() {
-      this.memoryAllocatorDump_ = undefined;
-    },
-
-    ready: function() {
-      this.updateContents_();
-    },
-
-    set memoryAllocatorDump(memoryAllocatorDump) {
-      this.memoryAllocatorDump_ = memoryAllocatorDump;
-      this.updateContents_();
-    },
-
-    get memoryAllocatorDump() {
-      return this.memoryAllocatorDump_;
-    },
-
-    updateContents_: function() {
-      this.$.contents.textContent = '';
-
-      if (this.memoryAllocatorDump_ === undefined) {
-        var infoText = this.ownerDocument.createElement('div');
-        this.$.contents.appendChild(infoText);
-        infoText.classList.add('info-text');
-        infoText.innerText = 'No memory allocator dump selected';
-        return;
+  (function() {
+    var IMPORTANCE_RULES = [
+      {
+        condition: 'size',
+        importance: 10
+      },
+      {
+        condition: 'outer_size',
+        importance: 9
+      },
+      {
+        condition: 'page_size',
+        importance: 0
+      },
+      {
+        condition: /size/,
+        importance: 5
+      },
+      {
+        importance: 0
       }
+    ];
 
-      var rows = this.createRows_();
-      var columns = this.createColumns_(rows);
+    Polymer({
+      // TODO(petrcermak): Consider sharing more code between
+      // tr-c-a-memory-dump-overview-pane and
+      // tr-c-a-memory-dump-allocator-details-pane (e.g. by defining a common
+      // base class tr-c-memory-dump-pane).
 
-      var table = this.ownerDocument.createElement(
-          'tracing-analysis-nested-table');
-      this.$.contents.appendChild(table);
-      table.tableRows = rows;
-      table.tableColumns = columns;
-      table.rebuild();
-    },
+      created: function() {
+        this.memoryAllocatorDump_ = undefined;
+      },
 
-    createRows_: function() {
-      var createAllocatorRow = function(allocatorDump) {
-        var cells = tv.b.mapItems(allocatorDump.attributes,
-            function(attrName, attrValue) {
-          return new tv.c.analysis.MemoryCell(attrValue);
-        });
-        var row = {
-          title: allocatorDump.name,
-          cells: cells
-        };
-        if (allocatorDump.children.length > 0)
-          row.subRows = allocatorDump.children.map(createAllocatorRow);
-        return row;
-      };
-      var rows = [createAllocatorRow(this.memoryAllocatorDump_)];
-      return rows;
-    },
+      ready: function() {
+        this.updateContents_();
+      },
 
-    createColumns_: function(rows) {
-      var titleColumn = {
-        title: 'Allocator',
-        value: function(row) {
-          return row.title;
-        },
-        width: '200px',
-        cmp: function(rowA, rowB) {
-          return rowA.title.localeCompare(rowB.title);
+      set memoryAllocatorDump(memoryAllocatorDump) {
+        this.memoryAllocatorDump_ = memoryAllocatorDump;
+        this.updateContents_();
+      },
+
+      get memoryAllocatorDump() {
+        return this.memoryAllocatorDump_;
+      },
+
+      updateContents_: function() {
+        this.$.contents.textContent = '';
+
+        if (this.memoryAllocatorDump_ === undefined) {
+          var infoText = this.ownerDocument.createElement('div');
+          this.$.contents.appendChild(infoText);
+          infoText.classList.add('info-text');
+          infoText.innerText = 'No memory allocator dump selected';
+          return;
         }
-      };
 
-      var attributeColumns = tv.c.analysis.MemoryColumn.fromRows(rows, 'cells');
-      tv.c.analysis.MemoryColumn.spaceEqually(attributeColumns);
+        var rows = this.createRows_();
+        var columns = this.createColumns_(rows);
 
-      var columns = [titleColumn].concat(attributeColumns);
-      return columns;
-    }
-  });
+        var table = this.ownerDocument.createElement(
+            'tr-b-ui-table');
+        this.$.contents.appendChild(table);
+        table.supportsSelection = true;
+        table.tableRows = rows;
+        table.tableColumns = columns;
+        table.rebuild();
+        tr.c.analysis.expandTableRowsRecursively(table);
+      },
+
+      createRows_: function() {
+        var createAllocatorRow = function(allocatorDump) {
+          var cells = tr.b.mapItems(allocatorDump.attributes,
+              function(attrName, attrValue) {
+            return new tr.c.analysis.MemoryCell(attrValue);
+          });
+          var row = {
+            title: allocatorDump.name,
+            cells: cells
+          };
+          if (allocatorDump.children.length > 0)
+            row.subRows = allocatorDump.children.map(createAllocatorRow);
+          return row;
+        };
+        var rows = [createAllocatorRow(this.memoryAllocatorDump_)];
+        return rows;
+      },
+
+      createColumns_: function(rows) {
+        var titleColumn = {
+          title: 'Allocator',
+          value: function(row) {
+            return row.title;
+          },
+          width: '200px',
+          cmp: function(rowA, rowB) {
+            return rowA.title.localeCompare(rowB.title);
+          }
+        };
+
+        var attributeColumns = tr.c.analysis.MemoryColumn.fromRows(
+            rows, 'cells');
+        tr.c.analysis.MemoryColumn.spaceEqually(attributeColumns);
+        tr.c.analysis.MemoryColumn.sortByImportance(
+            attributeColumns, IMPORTANCE_RULES);
+
+        var columns = [titleColumn].concat(attributeColumns);
+        return columns;
+      }
+    });
+  })();
   </script>
 </polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane_test.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane_test.html
index b67387f..b776ab6 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_allocator_details_pane_test.html
@@ -9,23 +9,23 @@
 <link rel="import"
     href="/core/analysis/memory_dump_allocator_details_pane.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/attribute.html">
-<link rel="import" href="/core/trace_model/container_memory_dump.html">
-<link rel="import" href="/core/trace_model/memory_allocator_dump.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/container_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var MemoryAllocatorDump = tv.c.trace_model.MemoryAllocatorDump;
-  var ContainerMemoryDump = tv.c.trace_model.ContainerMemoryDump;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+  var ContainerMemoryDump = tr.model.ContainerMemoryDump;
+  var ScalarAttribute = tr.model.ScalarAttribute;
 
   function createMemoryAllocatorDump() {
     var memoryDump = new ContainerMemoryDump(-10);
     var dump = new MemoryAllocatorDump(memoryDump, 'v8');
-    dump.addAttribute('outer_size',
+    dump.addAttribute('size',
         new ScalarAttribute('bytes', 1073741824) /* 1 GiB */);
     dump.addAttribute('inner_size',
         new ScalarAttribute('bytes', 2097152) /* 2 MiB */);
@@ -35,7 +35,7 @@
 
   test('instantiate_empty', function() {
     var viewEl = document.createElement(
-        'tv-c-memory-dump-allocator-details-pane');
+        'tr-c-a-memory-dump-allocator-details-pane');
     this.addHTMLOutput(viewEl);
   });
 
@@ -43,12 +43,12 @@
     var memoryAllocatorDump = createMemoryAllocatorDump();
 
     var viewEl = document.createElement(
-        'tv-c-memory-dump-allocator-details-pane');
+        'tr-c-a-memory-dump-allocator-details-pane');
     viewEl.memoryAllocatorDump = memoryAllocatorDump;
     this.addHTMLOutput(viewEl);
 
-    var table = tv.b.findDeepElementMatching(
-        viewEl, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        viewEl, 'tr-b-ui-table');
 
     var rows = table.tableRows;
     var columns = table.tableColumns;
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane.html
index 02d1aef..6bd570e 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane.html
@@ -11,11 +11,11 @@
 <link rel="import"
     href="/core/analysis/memory_dump_vm_regions_details_pane.html">
 <link rel="import" href="/core/analysis/memory_dump_sub_view_util.html">
-<link rel="import" href="/core/analysis/size_span.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/trace_model/attribute.html">
+<link rel="import" href="/base/units/size_in_bytes_span.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/model/attribute.html">
 
-<polymer-element name="tv-c-memory-dump-overview-pane">
+<polymer-element name="tr-c-a-memory-dump-overview-pane">
   <template>
     <style>
       :host {
@@ -41,138 +41,191 @@
       }
     </style>
     <div id="label">Overview</div>
-    <tracing-analysis-nested-table id="table">
-    </tracing-analysis-nested-table>
+    <tr-b-ui-table id="table">
+    </tr-b-ui-table>
   </template>
   <script>
   'use strict';
 
-  Polymer({
-    // TODO(petrcermak): Consider sharing more code between
-    // tv-c-memory-dump-overview-pane and tv-c-memory-dump-process pane
-    // (e.g. by defining a common base class tv-c-memory-dump-pane).
+  (function() {
+    var IMPORTANCE_RULES = [
+      {
+        condition: 'tracing',
+        importance: 0
+      },
+      {
+        importance: 1
+      }
+    ];
 
-    created: function() {
-      this.processMemoryDumps_ = undefined;
-    },
+    Polymer({
+      // TODO(petrcermak): Consider sharing more code between
+      // tr-c-a-memory-dump-overview-pane and tr-c-memory-dump-process pane
+      // (e.g. by defining a common base class tr-c-memory-dump-pane).
 
-    ready: function() {
-      this.$.table.supportsSelection = true;
-      this.$.table.cellSelectionMode = true;
-      this.$.table.addEventListener('selection-changed', function(tableEvent) {
-        tableEvent.stopPropagation();
-        var paneEvent = new Event('selected-memory-cell-changed', false, false);
-        this.dispatchEvent(paneEvent);
-      }.bind(this));
-    },
+      created: function() {
+        this.processMemoryDumps_ = undefined;
+      },
 
-    set processMemoryDumps(processMemoryDumps) {
-      this.processMemoryDumps_ = processMemoryDumps;
-      this.updateContents_();
-    },
+      ready: function() {
+        this.$.table.supportsSelection = true;
+        this.$.table.cellSelectionMode = true;
+        this.$.table.addEventListener('selection-changed',
+            function(tableEvent) {
+          tableEvent.stopPropagation();
+          var paneEvent = new Event('selected-memory-cell-changed');
+          this.dispatchEvent(paneEvent);
+        }.bind(this));
+      },
 
-    get processMemoryDumps() {
-      return this.processMemoryDumps_;
-    },
+      set processMemoryDumps(processMemoryDumps) {
+        this.processMemoryDumps_ = processMemoryDumps;
+        this.updateContents_();
+      },
 
-    get selectedMemoryCell() {
-      var selectedTableRow = this.$.table.selectedTableRow;
-      if (!selectedTableRow)
-        return undefined;
+      get processMemoryDumps() {
+        return this.processMemoryDumps_;
+      },
 
-      var selectedColumnIndex = this.$.table.selectedColumnIndex;
-      if (selectedColumnIndex === undefined)
-        return undefined;
+      get selectedMemoryCell() {
+        var selectedTableRow = this.$.table.selectedTableRow;
+        if (!selectedTableRow)
+          return undefined;
 
-      var selectedColumn = this.$.table.tableColumns[selectedColumnIndex];
-      var selectedMemoryCell = selectedColumn.cell(selectedTableRow);
-      return selectedMemoryCell;
-    },
+        var selectedColumnIndex = this.$.table.selectedColumnIndex;
+        if (selectedColumnIndex === undefined)
+          return undefined;
 
-    updateContents_: function() {
-      var processMemoryDumps = this.processMemoryDumps_ || [];
+        var selectedColumn = this.$.table.tableColumns[selectedColumnIndex];
+        var selectedMemoryCell = selectedColumn.cell(selectedTableRow);
+        return selectedMemoryCell;
+      },
 
-      var rows = processMemoryDumps.map(function(processMemoryDump) {
-        // Used memory (total resident, PSS).
-        var usedMemorySizes = {};
-        var totalResident = processMemoryDump.totalResidentBytes;
-        if (totalResident !== undefined) {
-          usedMemorySizes['Total used memory'] = new tv.c.analysis.MemoryCell(
-              new tv.c.trace_model.ScalarAttribute('bytes', totalResident));
-        }
-        var pss =
-            processMemoryDump.mostRecentTotalProportionalResidentSizeInBytes;
-        if (pss !== undefined) {
-          var cell = new tv.c.analysis.MemoryCell(
-              new tv.c.trace_model.ScalarAttribute('bytes', pss));
-          cell.buildDetailsPane = function() {
+      updateContents_: function() {
+        var processMemoryDumps = this.processMemoryDumps_ || [];
+
+        var rows = processMemoryDumps.map(function(processMemoryDump) {
+          function buildVMRegionsPane() {
             var pane = document.createElement(
-                'tv-c-memory-dump-vm-regions-details-pane');
+                    'tr-c-a-memory-dump-vm-regions-details-pane');
             pane.vmRegions = processMemoryDump.mostRecentVmRegions;
             return pane;
           }
-          usedMemorySizes['Proportional used memory (mmaps)'] = cell;
-        }
 
-        // Allocator memory (v8, oilpan, ...).
-        var allocatorSizes = {};
-        if (processMemoryDump.memoryAllocatorDumps !== undefined) {
-          processMemoryDump.memoryAllocatorDumps.forEach(function(dump) {
-            var cell = new tv.c.analysis.MemoryCell(
-                dump.attributes['outer_size']);
-            cell.buildDetailsPane = function() {
-              var pane = document.createElement(
-                  'tv-c-memory-dump-allocator-details-pane');
-              pane.memoryAllocatorDump = dump;
-              return pane;
-            };
-            allocatorSizes[dump.fullName] = cell;
-          }, this);
-        }
+          // Used memory (total resident, PSS, ...).
+          var usedMemorySizes = {};
+          var totalResident = processMemoryDump.totalResidentBytes;
+          if (totalResident !== undefined) {
+            var cell = new tr.c.analysis.MemoryCell(
+                new tr.model.ScalarAttribute('bytes', totalResident));
+            cell.buildDetailsPane = buildVMRegionsPane;
+            usedMemorySizes['Total resident'] = cell;
+          }
 
-        return {
-          title: processMemoryDump.process.userFriendlyName,
-          usedMemorySizes: usedMemorySizes,
-          allocatorSizes: allocatorSizes
+          function addByteStatCell(byteStatName, columnTitle) {
+            var byteStat =
+                processMemoryDump.getMostRecentTotalVmRegionStat(byteStatName);
+            if (byteStat !== undefined) {
+              var cell = new tr.c.analysis.MemoryCell(
+                  new tr.model.ScalarAttribute('bytes', byteStat));
+              cell.buildDetailsPane = buildVMRegionsPane;
+              usedMemorySizes[columnTitle] = cell;
+            }
+          }
+          addByteStatCell('proportionalResident', 'PSS');
+          addByteStatCell('privateDirtyResident', 'Private dirty');
+          addByteStatCell('swapped', 'Swapped');
+
+          // Allocator memory (v8, oilpan, ...).
+          var allocatorSizes = {};
+          if (processMemoryDump.memoryAllocatorDumps !== undefined) {
+            processMemoryDump.memoryAllocatorDumps.forEach(function(dump) {
+              var attr = dump.attributes['size'];
+              // TODO(petrcermak): Remove support for the old default attribute
+              // name once the correspoding change lands in Chromium.
+              if (attr === undefined)
+                attr = dump.attributes['outer_size'];
+              var cell = new tr.c.analysis.MemoryCell(attr);
+              cell.buildDetailsPane = function() {
+                var pane = document.createElement(
+                    'tr-c-a-memory-dump-allocator-details-pane');
+                pane.memoryAllocatorDump = dump;
+                return pane;
+              };
+              allocatorSizes[dump.fullName] = cell;
+            }, this);
+          }
+
+          return {
+            title: processMemoryDump.process.userFriendlyName,
+            usedMemorySizes: usedMemorySizes,
+            allocatorSizes: allocatorSizes
+          };
+        }, this);
+        this.$.table.tableRows = rows;
+
+        this.updateColumns_(rows);
+
+        this.$.table.rebuild();
+      },
+
+      updateColumns_: function(rows) {
+        var titleColumn = {
+          title: 'Process',
+          value: function(row) {
+            var titleEl = document.createElement('tr-b-ui-color-legend');
+            titleEl.label = row.title;
+            return titleEl;
+          },
+          width: '200px',
+          cmp: function(rowA, rowB) {
+            return rowA.title.localeCompare(rowB.title);
+          },
+          supportsCellSelection: false
         };
-      }, this);
-      this.$.table.tableRows = rows;
 
-      this.updateColumns_(rows);
-
-      this.$.table.rebuild();
-    },
-
-    updateColumns_: function(rows) {
-      var titleColumn = {
-        title: 'Process',
-        value: function(row) {
-          var titleEl = document.createElement('tv-b-color-legend');
-          titleEl.label = row.title;
+        var usedMemorySizeColumns = tr.c.analysis.MemoryColumn.fromRows(
+            rows, 'usedMemorySizes');
+        var allocatorSizeColumns = tr.c.analysis.MemoryColumn.fromRows(
+            rows, 'allocatorSizes', function(allocatorName) {
+          var titleEl = document.createElement('tr-b-ui-color-legend');
+          titleEl.label = allocatorName;
           return titleEl;
-        },
-        width: '200px',
-        cmp: function(rowA, rowB) {
-          return rowA.title.localeCompare(rowB.title);
-        },
-        supportsCellSelection: false
-      };
+        });
+        tr.c.analysis.MemoryColumn.sortByImportance(
+            allocatorSizeColumns, IMPORTANCE_RULES);
 
-      var usedMemorySizeColumns = tv.c.analysis.MemoryColumn.fromRows(
-          rows, 'usedMemorySizes');
-      var allocatorSizeColumns = tv.c.analysis.MemoryColumn.fromRows(
-          rows, 'allocatorSizes', function(allocatorName) {
-        var titleEl = document.createElement('tv-b-color-legend');
-        titleEl.label = allocatorName;
-        return titleEl;
-      });
+        // Grey the 'tracing' column out (if present).
+        // TODO(petrcermak): Find a less hacky way to do this.
+        var tracingColumn = tr.b.findFirstInArray(allocatorSizeColumns,
+            function(column) {
+          return column.name === 'tracing';
+        });
+        if (tracingColumn !== undefined) {
+          var titleEl = document.createElement('span');
+          titleEl.style.color = '#999';
+          titleEl.textContent = 'tracing';
+          tracingColumn.title = titleEl;
 
-      var sizeColumns = usedMemorySizeColumns.concat(allocatorSizeColumns);
-      tv.c.analysis.MemoryColumn.spaceEqually(sizeColumns);
+          var oldValueCallback = tracingColumn.value;
+          tracingColumn.value = function(row) {
+            var oldValue = oldValueCallback.call(this, row);
+            if (!(oldValue instanceof HTMLElement))
+              oldValue = document.createTextNode(oldValue);
+            var valueEl = document.createElement('span');
+            valueEl.style.color = '#999';
+            valueEl.appendChild(oldValue);
+            return valueEl;
+          };
+        }
 
-      var columns = [titleColumn].concat(sizeColumns);
-      this.$.table.tableColumns = columns;
-    }
-  });
+        var sizeColumns = usedMemorySizeColumns.concat(allocatorSizeColumns);
+        tr.c.analysis.MemoryColumn.spaceEqually(sizeColumns);
+
+        var columns = [titleColumn].concat(sizeColumns);
+        this.$.table.tableColumns = columns;
+      }
+    });
+  })();
   </script>
 </polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane_test.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane_test.html
index a926b8a..65a5d46 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_overview_pane_test.html
@@ -13,50 +13,73 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function createProcessMemoryDumps() {
-    var gmd = tv.c.analysis.createTestGlobalMemoryDump();
-    return tv.b.dictionaryValues(gmd.processMemoryDumps);
+    var gmd = tr.c.analysis.createTestGlobalMemoryDump();
+    return tr.b.dictionaryValues(gmd.processMemoryDumps);
   }
 
   test('instantiate', function() {
     var processMemoryDumps = createProcessMemoryDumps();
 
-    var viewEl = document.createElement('tv-c-memory-dump-overview-pane');
+    var viewEl = document.createElement('tr-c-a-memory-dump-overview-pane');
     viewEl.processMemoryDumps = processMemoryDumps;
     this.addHTMLOutput(viewEl);
 
-    var table = tv.b.findDeepElementMatching(
-        viewEl, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        viewEl, 'tr-b-ui-table');
 
     var rows = table.tableRows;
     var columns = table.tableColumns;
-    assert.lengthOf(rows, 2);
-    assert.lengthOf(columns, 5);
+    assert.lengthOf(rows, 3);
+    assert.lengthOf(columns, 9);
 
     var titleColumn = columns[0];
     var totalColumn = columns[1];
     var proportionalColumn = columns[2];
-    var oilpanColumn = columns[3];
-    var v8Column = columns[4];
+    var privateDirtyColumn = columns[3];
+    var swappedColumn = columns[4];
+    var mallocColumn = columns[5];
+    var v8Column = columns[6];
+    var oilpanColumn = columns[7];
+    var tracingColumn = columns[8];
 
     // Check the rows of the table.
     assert.equal(titleColumn.value(rows[0]).label, 'Process 1');
     assert.equal(totalColumn.value(rows[0]).numBytes, 31457280);
     assert.equal(proportionalColumn.value(rows[0]).numBytes, 10485760);
-    assert.equal(oilpanColumn.value(rows[0]), '');
+    assert.equal(privateDirtyColumn.value(rows[0]).numBytes, 8388608);
+    assert.equal(swappedColumn.value(rows[0]).numBytes, 0);
+    assert.equal(mallocColumn.value(rows[0]), '');
     assert.equal(v8Column.value(rows[0]), '');
+    assert.equal(oilpanColumn.value(rows[0]), '');
+    assert.equal(tracingColumn.value(rows[0]).textContent, '');
 
     assert.equal(titleColumn.value(rows[1]).label, 'Process 2');
-    assert.equal(proportionalColumn.value(rows[1]), '');
-    assert.equal(oilpanColumn.value(rows[1]).numBytes, 2147483648);
-    assert.equal(v8Column.value(rows[1]).numBytes, 1073741824);
+    assert.equal(totalColumn.value(rows[1]).numBytes, 19922944);
+    assert.equal(proportionalColumn.value(rows[1]).numBytes, 14680064);
+    assert.equal(privateDirtyColumn.value(rows[1]).numBytes, 524288);
+    assert.equal(swappedColumn.value(rows[1]).numBytes, 32);
+    assert.equal(mallocColumn.value(rows[1]).numBytes, 2097152);
+    assert.equal(v8Column.value(rows[1]).numBytes, 5242880);
+    assert.equal(oilpanColumn.value(rows[1]), '');
+    assert.equal(tracingColumn.value(rows[1]).children[0].numBytes, 1048576);
+
+    assert.equal(titleColumn.value(rows[2]).label, 'Process 3');
+    assert.equal(totalColumn.value(rows[2]), '');
+    assert.equal(proportionalColumn.value(rows[2]), '');
+    assert.equal(privateDirtyColumn.value(rows[2]), '');
+    assert.equal(swappedColumn.value(rows[2]), '');
+    assert.equal(mallocColumn.value(rows[2]), '');
+    assert.equal(v8Column.value(rows[2]).numBytes, 1073741824);
+    assert.equal(oilpanColumn.value(rows[2]).numBytes, 2147483648);
+    assert.equal(tracingColumn.value(rows[2]).textContent, '');
   });
 
   test('selection', function() {
     var processMemoryDumps = createProcessMemoryDumps();
 
-    var viewEl = document.createElement('tv-c-memory-dump-overview-pane');
+    var viewEl = document.createElement('tr-c-a-memory-dump-overview-pane');
     viewEl.processMemoryDumps = processMemoryDumps;
     this.addHTMLOutput(viewEl);
 
@@ -66,13 +89,13 @@
       didFireSelectedDumpChanged = true;
     });
 
-    var table = tv.b.findDeepElementMatching(
-        viewEl, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        viewEl, 'tr-b-ui-table');
 
     // Simulate clicking on the 'oilpan' cell of the second process.
     didFireSelectedDumpChanged = false;
-    table.selectedTableRow = table.tableRows[1];
-    table.selectedColumnIndex = 3;
+    table.selectedTableRow = table.tableRows[2];
+    table.selectedColumnIndex = 7;
     assert.isTrue(didFireSelectedDumpChanged);
     assert.isDefined(viewEl.selectedMemoryCell);
     assert.isDefined(viewEl.selectedMemoryCell.buildDetailsPane);
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_test_utils.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_test_utils.html
index 36c88c3..67c9e37 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_test_utils.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_test_utils.html
@@ -6,10 +6,10 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/attribute.html">
-<link rel="import" href="/core/trace_model/global_memory_dump.html">
-<link rel="import" href="/core/trace_model/memory_allocator_dump.html">
-<link rel="import" href="/core/trace_model/process_memory_dump.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/global_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
+<link rel="import" href="/model/process_memory_dump.html">
 
 <script>
 'use strict';
@@ -17,26 +17,32 @@
 /**
  * @fileoverview Helper functions for memory dump analysis sub-view tests.
  */
-tv.exportTo('tv.c.analysis', function() {
-  var GlobalMemoryDump = tv.c.trace_model.GlobalMemoryDump;
-  var ProcessMemoryDump = tv.c.trace_model.ProcessMemoryDump;
-  var MemoryAllocatorDump = tv.c.trace_model.MemoryAllocatorDump;
-  var VMRegion = tv.c.trace_model.VMRegion;
-  var VMRegionByteStats = tv.c.trace_model.VMRegionByteStats;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
+tr.exportTo('tr.c.analysis', function() {
+  var GlobalMemoryDump = tr.model.GlobalMemoryDump;
+  var ProcessMemoryDump = tr.model.ProcessMemoryDump;
+  var MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+  var VMRegion = tr.model.VMRegion;
+  var VMRegionByteStats = tr.model.VMRegionByteStats;
+  var ScalarAttribute = tr.model.ScalarAttribute;
 
   function createTestGlobalMemoryDump() {
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       var p1 = model.getOrCreateProcess(1);
       var p2 = model.getOrCreateProcess(2);
+      var p3 = model.getOrCreateProcess(3);
 
       var gmd = new GlobalMemoryDump(model, 42);
       model.globalMemoryDumps.push(gmd);
 
+      function addProcessMemoryDump(process, timestamp) {
+        var pmd = new ProcessMemoryDump(gmd, process, timestamp);
+        process.memoryDumps.push(pmd);
+        gmd.processMemoryDumps[process.pid] = pmd;
+        return pmd;
+      }
+
       // One process with VM regions.
-      var pmd1 = new ProcessMemoryDump(gmd, p1, 41);
-      p1.memoryDumps.push(pmd1);
-      gmd.processMemoryDumps[p1.pid] = pmd1;
+      var pmd1 = addProcessMemoryDump(p1, 41);
       pmd1.totalResidentBytes = 31457280 /* 30 MiB */;
       pmd1.vmRegions = [
         VMRegion.fromDict({
@@ -44,29 +50,59 @@
             sizeInBytes: 20971520, /* 20 MiB */
             protectionFlags: VMRegion.PROTECTION_FLAG_READ,
             mappedFile: '[stack]',
-            byteStats: VMRegionByteStats.fromDict({
-                privateResident: 8388608, /* 8 MiB */
-                sharedResident: 12582912, /* 12 MiB */
+            byteStats: {
+                privateDirtyResident: 8388608, /* 8 MiB */
+                sharedCleanResident: 12582912, /* 12 MiB */
                 proportionalResident: 10485760 /* 10 MiB */
-            })
+            }
         })
       ];
 
-      // One process with allocator dumps.
-      var pmd2 = new ProcessMemoryDump(gmd, p2, 43);
-      p2.memoryDumps.push(pmd2);
-      gmd.processMemoryDumps[p2.pid] = pmd2;
+      var pmd2 = addProcessMemoryDump(p2, 42);
+      pmd2.totalResidentBytes = 20971520 /* 20 MiB */;
+      pmd2.vmRegions = [
+        VMRegion.fromDict({
+          startAddress: 256,
+          sizeInBytes: 6000,
+          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+              VMRegion.PROTECTION_FLAG_WRITE,
+          mappedFile: '[stack:20310]',
+          byteStats: {
+            proportionalResident: 15728640, /* 15 MiB */
+            privateDirtyResident: 1572864, /* 1.5 MiB */
+            swapped: 32 /* 32 B */
+          }
+        })
+      ];
       pmd2.memoryAllocatorDumps = (function() {
-        var oilpanDump = new MemoryAllocatorDump(pmd2, 'oilpan');
-        oilpanDump.addAttribute('outer_size',
+        var mallocDump = new MemoryAllocatorDump(pmd2, 'malloc');
+        mallocDump.addAttribute('size',
+            new ScalarAttribute('bytes', 3145728) /* 3 MiB */);
+
+        var v8Dump = new MemoryAllocatorDump(pmd2, 'v8');
+        v8Dump.addAttribute('size',
+            new ScalarAttribute('bytes', 5242880) /* 5 MiB */);
+
+        var tracingDump = new MemoryAllocatorDump(pmd2, 'tracing');
+        tracingDump.addAttribute('size',
+            new ScalarAttribute('bytes', 1048576) /* 1 MiB */);
+
+        return [mallocDump, v8Dump, tracingDump];
+      })();
+
+      // One process with allocator dumps.
+      var pmd3 = addProcessMemoryDump(p3, 43);
+      pmd3.memoryAllocatorDumps = (function() {
+        var oilpanDump = new MemoryAllocatorDump(pmd3, 'oilpan');
+        oilpanDump.addAttribute('size',
             new ScalarAttribute('bytes', 2147483648) /* 2 GiB */);
         oilpanDump.addAttribute('inner_size',
             new ScalarAttribute('bytes', 5242880) /* 5 MiB */);
         oilpanDump.addAttribute('objects_count',
             new ScalarAttribute('objects', 2015));
 
-        var v8Dump = new MemoryAllocatorDump(pmd2, 'v8');
-        v8Dump.addAttribute('outer_size',
+        var v8Dump = new MemoryAllocatorDump(pmd3, 'v8');
+        v8Dump.addAttribute('size',
             new ScalarAttribute('bytes', 1073741824) /* 1 GiB */);
         v8Dump.addAttribute('inner_size',
             new ScalarAttribute('bytes', 2097152) /* 2 MiB */);
@@ -82,7 +118,7 @@
 
   function createTestProcessMemoryDumps() {
     var globalMemoryDump = createTestGlobalMemoryDump();
-    return tv.b.dictionaryValues(globalMemoryDump.processMemoryDumps);
+    return tr.b.dictionaryValues(globalMemoryDump.processMemoryDumps);
   }
 
   function createTestProcessMemoryDump() {
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util.html
index 29ed1ca..21bf30c 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/core/analysis/size_span.html">
+<link rel="import" href="/base/units/size_in_bytes_span.html">
 
 <script>
 'use strict';
@@ -14,14 +14,15 @@
 /**
  * @fileoverview Helper code for memory dump sub-views.
  */
-tv.exportTo('tv.c.analysis', function() {
+tr.exportTo('tr.c.analysis', function() {
 
   /**
    * A table builder column for displaying memory dump data.
    *
    * @constructor
    */
-  function MemoryColumn(title, units, cellGetter) {
+  function MemoryColumn(name, title, units, cellGetter) {
+    this.name = name;
     this.title = title;
     this.units = units;
     this.cell = cellGetter;
@@ -34,7 +35,7 @@
       if (row === undefined)
         return;
       var attrCells = row[cellKey];
-      tv.b.iterItems(attrCells, function(attrName, attrCell) {
+      tr.b.iterItems(attrCells, function(attrName, attrCell) {
         if (attrCell === undefined)
           return;
         var attrValue = attrCell.attr;
@@ -50,7 +51,7 @@
         }
         if (existingTraits.constructor !== attrValue.constructor ||
             existingTraits.units !== attrValue.units) {
-          existingTraits.constructor = tv.c.trace_model.UnknownAttribute;
+          existingTraits.constructor = tr.model.UnknownAttribute;
           existingTraits.units = undefined;
         }
       });
@@ -59,26 +60,26 @@
     };
     rows.forEach(gatherTraits);
 
-    var titleBuilder = opt_titleBuilder || tv.b.identity;
+    var titleBuilder = opt_titleBuilder || tr.b.identity;
 
     var columns = [];
-    tv.b.iterItems(columnTraits, function(columnName, columnTraits) {
+    tr.b.iterItems(columnTraits, function(columnName, columnTraits) {
       var cellGetter = fieldGetter(cellKey, columnName);
       var title = titleBuilder(columnName);
       columns.push(MemoryColumn.fromAttributeTraits(
-          title, columnTraits, cellGetter));
+          columnName, title, columnTraits, cellGetter));
     });
 
     return columns;
   };
 
-  MemoryColumn.fromAttributeTraits = function(title, traits, cellGetter) {
+  MemoryColumn.fromAttributeTraits = function(name, title, traits, cellGetter) {
     var constructor;
-    if (traits.constructor === tv.c.trace_model.ScalarAttribute)
+    if (traits.constructor === tr.model.ScalarAttribute)
       constructor = ScalarMemoryColumn;
     else
       constructor = MemoryColumn;
-    return new constructor(title, traits.units, cellGetter);
+    return new constructor(name, title, traits.units, cellGetter);
   };
 
   MemoryColumn.spaceEqually = function(columns) {
@@ -88,6 +89,67 @@
     });
   };
 
+  /**
+   * Sort a list of memory columns according to a list of importance rules.
+   * This function modifies the original array and doesn't return anything.
+   *
+   * The list of importance rules contains objects with mandatory 'importance'
+   * numeric fields and optional 'condition' string or regex fields. Example:
+   *
+   *   var importanceRules = [
+   *     {
+   *       condition: 'page_size',
+   *       importance: 8
+   *     },
+   *     {
+   *       condition: /size/,
+   *       importance: 10
+   *     },
+   *     {
+   *       // No condition: matches all columns.
+   *       importance: 9
+   *     }
+   *   ];
+   *
+   * The importance of a column is determined by the first rule whose condition
+   * matches the column's name, so the rules above will sort a generic list of
+   * columns into three groups as follows:
+   *
+   *      [most important, left in the resulting table]
+   *   1. columns whose name contains 'size' excluding 'page_size' because it
+   *      would have already matched the first rule (Note that string matches
+   *      must be exact so a column named 'page_size2' would not match the
+   *      first rule and would therefore belong to this group).
+   *   2. columns whose name does not contain 'size'.
+   *   3. columns whose name is 'page_size'.
+   *      [least important, right in the resulting table]
+   *
+   * where the order within each group is unmodified (stable sort).
+   */
+  MemoryColumn.sortByImportance = function(columns, importanceRules) {
+    var positions = columns.map(function(column, srcIndex) {
+      return {
+        importance: column.getImportance(importanceRules),
+        srcIndex: srcIndex,
+        column: column
+      };
+    });
+
+    positions.sort(function(a, b) {
+      // Keep existing order of columns if they have the same importance
+      // (stable sort).
+      if (a.importance === b.importance)
+        return a.srcIndex - b.srcIndex;
+
+      // Sort columns in descending order of importance.
+      return b.importance - a.importance;
+    });
+
+    positions.forEach(function(position, dstIndex) {
+      columns[dstIndex] = position.column;
+    });
+  };
+
   MemoryColumn.prototype = {
     attr: function(row) {
       var cell = this.cell(row);
@@ -123,14 +185,46 @@
       var strA = String(attrA.value);
       var strB = String(attrB.value);
       return strA.localeCompare(strB);
+    },
+
+    getImportance: function(importanceRules) {
+      if (importanceRules.length === 0)
+        return 0;
+
+      // Find the first matching rule.
+      for (var i = 0; i < importanceRules.length; i++) {
+        var importanceRule = importanceRules[i];
+        if (this.matchesNameCondition(importanceRule.condition))
+          return importanceRule.importance;
+      }
+
+      // No matching rule. Return lower importance than all rules.
+      var minImportance = importanceRules[0].importance;
+      for (var i = 1; i < importanceRules.length; i++) {
+        minImportance = Math.min(minImportance, importanceRules[i].importance);
+      }
+      return minImportance - 1;
+    },
+
+    matchesNameCondition: function(condition) {
+      // Rules without conditions match all columns.
+      if (condition === undefined)
+        return true;
+
+      // String conditions must match the column name exactly.
+      if (typeof(condition) === 'string')
+        return this.name === condition;
+
+      // If the condition is not a string, assume it is a RegExp.
+      return condition.test(this.name);
     }
   };
 
   /**
    * @constructor
    */
-  function ScalarMemoryColumn(title, units, cellGetter) {
-    MemoryColumn.call(this, title, units, cellGetter);
+  function ScalarMemoryColumn(name, title, units, cellGetter) {
+    MemoryColumn.call(this, name, title, units, cellGetter);
   }
 
   ScalarMemoryColumn.prototype = {
@@ -138,7 +232,7 @@
 
     formatDefinedAttribute: function(attr) {
       if (this.units === 'bytes') {
-        var sizeEl = document.createElement('tv-c-a-size-span');
+        var sizeEl = document.createElement('tr-b-u-size-in-bytes-span');
         sizeEl.numBytes = attr.value;
         return sizeEl;
       }
@@ -158,7 +252,7 @@
   }
 
   function fieldGetter(/* fields */) {
-    var fields = tv.b.asArray(arguments);
+    var fields = tr.b.asArray(arguments);
     return function(row) {
       var value = row;
       for (var i = 0; i < fields.length; i++)
@@ -167,11 +261,27 @@
     };
   }
 
+  /** Limit for the number of sub-rows for recursive table row expansion. */
+  var RECURSIVE_EXPANSION_MAX_SUB_ROW_COUNT = 10;
+
+  function expandTableRowsRecursively(table) {
+    function expandRowRecursively(row) {
+      if (row.subRows === undefined || row.subRows.length === 0)
+        return;
+      if (row.subRows.length > RECURSIVE_EXPANSION_MAX_SUB_ROW_COUNT)
+        return;
+      table.setExpandedForTableRow(row, true);
+      row.subRows.forEach(expandRowRecursively);
+    }
+    table.tableRows.forEach(expandRowRecursively);
+  }
+
   return {
     MemoryColumn: MemoryColumn,
     ScalarMemoryColumn: ScalarMemoryColumn,
     MemoryCell: MemoryCell,
-    fieldGetter: fieldGetter
+    fieldGetter: fieldGetter,
+    expandTableRowsRecursively: expandTableRowsRecursively
   };
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util_test.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util_test.html
index 81b7485..9037cd2 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_sub_view_util_test.html
@@ -5,20 +5,22 @@
 found in the LICENSE file.
 -->
 
+<link rel="import" href="/base/ui/table.html">
 <link rel="import" href="/core/analysis/memory_dump_sub_view_util.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/attribute.html">
+<link rel="import" href="/model/attribute.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var MemoryColumn = tv.c.analysis.MemoryColumn;
-  var ScalarMemoryColumn = tv.c.analysis.ScalarMemoryColumn;
-  var MemoryCell = tv.c.analysis.MemoryCell;
-  var fieldGetter = tv.c.analysis.fieldGetter;
-  var StringAttribute = tv.c.trace_model.StringAttribute;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
+tr.b.unittest.testSuite(function() {
+  var MemoryColumn = tr.c.analysis.MemoryColumn;
+  var ScalarMemoryColumn = tr.c.analysis.ScalarMemoryColumn;
+  var MemoryCell = tr.c.analysis.MemoryCell;
+  var fieldGetter = tr.c.analysis.fieldGetter;
+  var expandTableRowsRecursively = tr.c.analysis.expandTableRowsRecursively;
+  var StringAttribute = tr.model.StringAttribute;
+  var ScalarAttribute = tr.model.ScalarAttribute;
 
   function checkPercent(string, expectedPercent) {
     assert.equal(Number(string.slice(0, -1)), expectedPercent);
@@ -123,8 +125,9 @@
       units: 'Mbps'
     };
     var column = MemoryColumn.fromAttributeTraits(
-        'First Column', traits, fieldGetter('x'));
+        'first_column', 'First Column', traits, fieldGetter('x'));
     assert.instanceOf(column, MemoryColumn);
+    assert.equal(column.name, 'first_column');
     assert.equal(column.title, 'First Column');
     assert.isUndefined(column.width);
     assert.equal(column.value({x: buildStringCell('Mbps', 'very fast')}),
@@ -138,8 +141,9 @@
       units: 'bytes'
     };
     var column = MemoryColumn.fromAttributeTraits(
-        'Second Column', traits, fieldGetter('x'));
+        'second_column', 'Second Column', traits, fieldGetter('x'));
     assert.instanceOf(column, MemoryColumn);
+    assert.equal(column.name, 'second_column');
     assert.equal(column.title, 'Second Column');
     assert.isUndefined(column.width);
     assert.equal(column.value({x: buildScalarCell('bytes', 1024)}).numBytes,
@@ -179,8 +183,44 @@
     checkPercent(columns[1].width, 50);
   });
 
+  test('checkMemoryColumn_sortByImportance', function() {
+    var columns = [
+      new MemoryColumn(
+          'page_size', 'Page Size', 'bytes', fieldGetter('pgsize')),
+      new MemoryColumn(
+          'resident_size', 'Resident Size', 'bytes', fieldGetter('rss')),
+      new MemoryColumn(
+          'object_count', 'Object Count', 'objects', fieldGetter('objcount')),
+      new MemoryColumn(
+          'proportional_size', 'Proportional Size', 'bytes', fieldGetter('pss'))
+    ];
+
+    var rules = [
+      {
+        condition: 'page_size',
+        importance: 8
+      },
+      {
+        condition: /size/,
+        importance: 10
+      },
+      {
+        importance: 9
+      }
+    ];
+
+    MemoryColumn.sortByImportance(columns, rules);
+
+    assert.lengthOf(columns, 4);
+    assert.equal(columns[0].name, 'resident_size');
+    assert.equal(columns[1].name, 'proportional_size');
+    assert.equal(columns[2].name, 'object_count');
+    assert.equal(columns[3].name, 'page_size');
+  });
+
   test('checkMemoryColumn_attr', function() {
-    var c = new MemoryColumn('Test Column', 'ms', fieldGetter('x'));
+    var c = new MemoryColumn(
+        'test_column', 'Test Column', 'ms', fieldGetter('x'));
 
     // Undefined cell.
     var row = {};
@@ -197,7 +237,8 @@
   });
 
   test('checkMemoryColumn_value', function() {
-    var c = new MemoryColumn('Test Column', 'ms', fieldGetter('x'));
+    var c = new MemoryColumn(
+        'test_column', 'Test Column', 'ms', fieldGetter('x'));
     assert.equal(c.title, 'Test Column');
     assert.isUndefined(c.width);
 
@@ -211,7 +252,8 @@
   });
 
   test('checkMemoryColumn_cmp', function() {
-    var c = new MemoryColumn('Test Column', 'ms', fieldGetter('x'));
+    var c = new MemoryColumn(
+        'test_column', 'Test Column', 'ms', fieldGetter('x'));
 
     // Cell (or the associated attribute) undefined in one or both rows.
     assert.equal(c.cmp({}, {y: new MemoryCell(undefined)}), 0);
@@ -227,8 +269,67 @@
         {x: buildStringCell('v', 'smaLL')}), 0);
   });
 
+  test('checkMemoryColumn_getImportance', function() {
+    var c = new ScalarMemoryColumn(
+        'test_column', 'Test Column', 'bytes', fieldGetter('x'));
+
+    var rules1 = [];
+    assert.equal(c.getImportance(rules1), 0);
+
+    var rules2 = [
+      {
+        condition: 'test',
+        importance: 4
+      },
+      {
+        condition: /test$/,
+        importance: 2
+      }
+    ];
+    assert.equal(c.getImportance(rules2), 1);
+
+    var rules3 = [
+      {
+        condition: 'test_column',
+        importance: 10
+      },
+      {
+        importance: 5
+      }
+    ];
+    assert.equal(c.getImportance(rules3), 10);
+
+    var rules4 = [
+      {
+        condition: 'test_column2',
+        importance: 8
+      },
+      {
+        condition: /column/,
+        importance: 12
+      }
+    ];
+    assert.equal(c.getImportance(rules4), 12);
+  });
+
+  test('checkMemoryColumn_matchesNameCondition', function() {
+    var c = new ScalarMemoryColumn(
+        'test_column', 'Test Column', 'bytes', fieldGetter('x'));
+
+    assert.isTrue(c.matchesNameCondition(undefined));
+
+    assert.isFalse(c.matchesNameCondition('test'));
+    assert.isTrue(c.matchesNameCondition('test_column'));
+    assert.isFalse(c.matchesNameCondition('test_column2'));
+
+    assert.isTrue(c.matchesNameCondition(/test/));
+    assert.isTrue(c.matchesNameCondition(/^[^_]*_[^_]*$/));
+    assert.isFalse(c.matchesNameCondition(/test$/));
+  });
+
   test('checkScalarMemoryColumn_value', function() {
-    var c = new ScalarMemoryColumn('Test Column', 'bytes', fieldGetter('x'));
+    var c = new ScalarMemoryColumn(
+        'test_column', 'Test Column', 'bytes', fieldGetter('x'));
     assert.equal(c.title, 'Test Column');
     assert.isUndefined(c.width);
 
@@ -242,7 +343,8 @@
   });
 
   test('checkScalarMemoryColumn_cmp', function() {
-    var c = new ScalarMemoryColumn('Test Column', 'ms', fieldGetter('x'));
+    var c = new ScalarMemoryColumn(
+        'test_column', 'Test Column', 'ms', fieldGetter('x'));
 
     // Cell (or the associated attribute) undefined in one or both rows.
     assert.equal(c.cmp({}, {y: new MemoryCell(undefined)}), 0);
@@ -273,5 +375,90 @@
     var f = fieldGetter('b', 'd', 'f');
     assert.equal(f({a: 0, b: {c: 0, d: {e: 0, f: 42}}}), 42);
   });
+
+  test('checkExpandTableRowsRecursively', function() {
+    var columns = [
+      {
+        title: 'Single column',
+        value: function(row) { return row.data; },
+        width: '100px'
+      }
+    ];
+
+    var rows = [
+      {
+        data: 'allocated',
+        subRows: [
+          {
+            data: 'v8'
+          },
+          {
+            data: 'oilpan',
+            subRows: [
+              { data: 'heaps' },
+              { data: 'objects' }
+            ]
+          },
+          {
+            data: 'skia',
+            subRows: [
+              { data: 'way' },
+              { data: 'too' },
+              { data: 'many' },
+              { data: 'sub-' },
+              { data: 'rows' },
+              { data: 'so' },
+              { data: 'that' },
+              { data: 'they' },
+              { data: 'wouldn\'t' },
+              { data: 'be' },
+              { data: 'auto-' },
+              { data: 'expanded' }
+            ]
+          }
+        ]
+      },
+      {
+        data: 'overhead',
+        subRows: [
+          {
+            data: 'internal_fragmentation'
+          },
+          {
+            data: 'external_fragmentation',
+            subRows: []
+          }
+        ]
+      }
+    ];
+
+    var table = document.createElement('tr-b-ui-table');
+    table.tableColumns = columns;
+    table.tableRows = rows;
+    table.rebuild();
+
+    expandTableRowsRecursively(table);
+
+    // 'allocated' row should be expanded.
+    assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+    // 'allocated/v8' row cannot be expanded (no sub-rows).
+    assert.isFalse(table.getExpandedForTableRow(rows[0].subRows[0]));
+
+    // 'allocated/oilpan' row should be expanded.
+    assert.isTrue(table.getExpandedForTableRow(rows[0].subRows[1]));
+
+    // 'allocated/skia' row should not be expanded (more than 10 sub-rows).
+    assert.isFalse(table.getExpandedForTableRow(rows[0].subRows[2]));
+
+    // 'overhead' row should be expanded.
+    assert.isTrue(table.getExpandedForTableRow(rows[1]));
+
+    // 'overhead/internal_fragmentation' cannot be expanded (no sub-rows).
+    assert.isFalse(table.getExpandedForTableRow(rows[1].subRows[0]));
+
+    // 'overhead/external_fragmentation' cannot be expanded (no sub-rows).
+    assert.isFalse(table.getExpandedForTableRow(rows[1].subRows[1]));
+  });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_view.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_view.html
index de881b2..4882e3d 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_view.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/core/analysis/memory_dump_overview_pane.html">
 
-<polymer-element name="tv-c-memory-dump-view">
+<polymer-element name="tr-c-a-memory-dump-view">
   <template>
     <style>
     :host {
@@ -20,8 +20,8 @@
       flex: 0 0 auto;
     }
     </style>
-    <tv-c-memory-dump-overview-pane id="overview_pane">
-    </tv-c-memory-dump-overview-pane>
+    <tr-c-a-memory-dump-overview-pane id="overview_pane">
+    </tr-c-a-memory-dump-overview-pane>
     <div id="details_pane_container">
     </div>
   </template>
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_view_test.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_view_test.html
index fca6819..a2ff2e9 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_view_test.html
@@ -13,40 +13,50 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var createTestProcessMemoryDumps = tv.c.analysis.createTestProcessMemoryDumps;
+tr.b.unittest.testSuite(function() {
+  var createTestProcessMemoryDumps = tr.c.analysis.createTestProcessMemoryDumps;
 
   test('instantiate', function() {
     var processMemoryDumps = createTestProcessMemoryDumps();
 
-    var viewEl = document.createElement('tv-c-memory-dump-view');
+    var viewEl = document.createElement('tr-c-a-memory-dump-view');
     viewEl.processMemoryDumps = processMemoryDumps;
     this.addHTMLOutput(viewEl);
 
-    var overviewPane = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-memory-dump-overview-pane');
-    var overviewTable = tv.b.findDeepElementMatching(
-        overviewPane, 'tracing-analysis-nested-table');
-    assert.lengthOf(overviewTable.tableRows, 2);
+    var overviewPane = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-memory-dump-overview-pane');
+    var overviewTable = tr.b.findDeepElementMatching(
+        overviewPane, 'tr-b-ui-table');
+    assert.lengthOf(overviewTable.tableRows, 3);
+    assert.lengthOf(overviewTable.tableColumns, 9);
 
-    // Select totals dump of first process.
+    // Select totals of first process.
     overviewTable.selectedTableRow = overviewTable.tableRows[0];
     overviewTable.selectedColumnIndex = 1;
+    var detailsPane = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-memory-dump-vm-regions-details-pane');
+    assert.strictEqual(
+        detailsPane.vmRegions, processMemoryDumps[0].mostRecentVmRegions);
 
-    // Select mmaps dump of first process.
+    // Select PSS of first process.
     overviewTable.selectedColumnIndex = 2;
+    var detailsPane = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-memory-dump-vm-regions-details-pane');
+    assert.strictEqual(
+        detailsPane.vmRegions, processMemoryDumps[0].mostRecentVmRegions);
 
-    // Select mmaps dump of second process.
-    overviewTable.selectedTableRow = overviewTable.tableRows[1];
+    // Select PSS of third process.
+    overviewTable.selectedTableRow = overviewTable.tableRows[2];
+    var detailsPane = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-memory-dump-vm-regions-details-pane');
+    assert.isUndefined(detailsPane);
 
     // Select oilpan dump of second process.
-    overviewTable.selectedColumnIndex = 3;
-
-    // There should now be an allocator details pane containing contain a table.
-    var detailsPane = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-memory-dump-allocator-details-pane');
-    var detailsTable = tv.b.findDeepElementMatching(
-        detailsPane, 'tracing-analysis-nested-table');
+    overviewTable.selectedColumnIndex = 7;
+    var detailsPane = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-memory-dump-allocator-details-pane');
+    var detailsTable = tr.b.findDeepElementMatching(
+        detailsPane, 'tr-b-ui-table');
     assert.lengthOf(detailsTable.tableRows, 1);
   });
 });
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane.html
index 22b92b5..0a808fa 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane.html
@@ -6,10 +6,10 @@
 -->
 
 <link rel="import" href="/core/analysis/memory_dump_sub_view_util.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/trace_model/attribute.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/model/attribute.html">
 
-<polymer-element name="tv-c-memory-dump-vm-regions-details-pane">
+<polymer-element name="tr-c-a-memory-dump-vm-regions-details-pane">
   <template>
     <style>
       :host {
@@ -48,71 +48,168 @@
   <script>
   'use strict';
 
-  Polymer({
-    // TODO(petrcermak): Consider sharing more code between
-    // tv-c-memory-dump-allocator-details-pane and
-    // tv-c-memory-dump-vm-regions-details-pane (e.g. by defining a common base
-    // class tv-c-memory-dump-details-pane).
+  (function() {
+    /**
+     * Rules for classifying memory maps.
+     *
+     * These rules are derived from core/jni/android_os_Debug.cpp in Android.
+     */
+    var CLASSIFICATION_RULES = {
+      name: 'Total',
+      children: [
+        {
+          name: 'Android',
+          file: /^\/dev\/ashmem/,
+          children: [
+            {
+              name: 'Java runtime',
+              file: /^\/dev\/ashmem\/dalvik-.*$/,
+              children: [
+                {
+                  name: 'Spaces',
+                  file: /\bspace/,
+                  children: [
+                    {
+                      name: 'Normal',
+                      file: /(alloc)|(main)/
+                    },
+                    {
+                      name: 'Large',
+                      file: /large.object/
+                    },
+                    {
+                      name: 'Zygote',
+                      file: /zygote/
+                    },
+                    {
+                      name: 'Non-moving',
+                      file: /non.moving/
+                    }
+                  ]
+                },
+                {
+                  name: 'Linear Alloc',
+                  file: /LinearAlloc/
+                },
+                {
+                  name: 'Indirect Reference Table',
+                  file: /indirect.ref/
+                },
+                {
+                  name: 'Cache',
+                  file: /jit-code-cache/
+                },
+                {
+                  name: 'Accounting'
+                }
+              ]
+            },
+            {
+              name: 'Cursor',
+              file: /CursorWindow/
+            },
+            {
+              name: 'Ashmem'
+            }
+          ]
+        },
+        {
+          name: 'Native heap',
+          file: /^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|$)/
+        },
+        {
+          name: 'Stack',
+          file: /^\[stack/
+        },
+        {
+          name: 'Files',
+          file: /\.((((so)|(jar)|(apk)|(ttf)|(odex)|(oat)|(arg))$)|(dex))/,
+          children: [
+            {
+              name: 'so',
+              file: /\.so$/
+            },
+            {
+              name: 'jar',
+              file: /\.jar$/
+            },
+            {
+              name: 'apk',
+              file: /\.apk$/
+            },
+            {
+              name: 'ttf',
+              file: /\.ttf$/
+            },
+            {
+              name: 'dex',
+              file: /\.((dex)|(odex$))/
+            },
+            {
+              name: 'oat',
+              file: /\.oat$/
+            },
+            {
+              name: 'art',
+              file: /\.art$/
+            }
+          ]
+        },
+        {
+          name: 'Devices',
+          file: /(^\/dev\/)|(anon_inode:dmabuf)/,
+          children: [
+            {
+              name: 'GPU',
+              file: /\/((nv)|(mali)|(kgsl))/
+            },
+            {
+              name: 'DMA',
+              file: /anon_inode:dmabuf/
+            }
+          ]
+        },
+        {
+          // Add a separate category for the discounted tracing overhead to
+          // avoid negative 'Total/Other' sizes.
+          name: 'Discounted tracing overhead',
+          file: /\[discounted tracing overhead\]/
+        }
+      ]
+    };
 
-    created: function() {
-      this.vmRegions_ = undefined;
-    },
+    /**
+     * Create a tree of nested rows (containing no mmaps) corresponding to a
+     * tree of classification rules.
+     */
+    function createEmptyRow(rule) {
+      var row = {
+        title: rule.name,
+        rule: rule,
+        cells: {},
+        subRows: []
+      };
+      if (rule.children !== undefined)
+        row.subRows = rule.children.map(createEmptyRow);
+      return row;
+    }
 
-    ready: function() {
-      this.updateContents_();
-    },
+    function hexString(address, is64BitAddress) {
+      var hexPadding = is64BitAddress ? '0000000000000000' : '00000000';
+      if (address === undefined)
+        return undefined;
+      return (hexPadding + address.toString(16)).substr(-hexPadding.length);
+    }
 
-    set vmRegions(vmRegions) {
-      this.vmRegions_ = vmRegions;
-      this.updateContents_();
-    },
-
-    get vmRegions() {
-      return this.vmRegions_;
-    },
-
-    updateContents_: function() {
-      this.$.contents.textContent = '';
-
-      if (this.vmRegions_ === undefined) {
-        var infoText = this.ownerDocument.createElement('div');
-        this.$.contents.appendChild(infoText);
-        infoText.classList.add('info-text');
-        infoText.innerText = 'No memory maps selected';
-        return;
-      }
-
-      var rows = this.createRows_();
-      var columns = this.createColumns_(rows);
-
-      var table = this.ownerDocument.createElement(
-          'tracing-analysis-nested-table');
-      this.$.contents.appendChild(table);
-      table.supportsSelection = true;
-      table.tableRows = rows;
-      table.tableColumns = columns;
-      table.rebuild();
-    },
-
-    createRows_: function() {
-      // TODO(petrcermak): Figure out if there's a cleaner way to do this.
-      var use64Bits = this.vmRegions_.some(function(vmRegion) {
-        if (vmRegion.startAddress === undefined)
-          return;
-        return vmRegion.startAddress >= 4294967296 /* 2^32 */;
-      });
-      var hexPadding = use64Bits ? '0000000000000000' : '00000000';
-      function hexString(address) {
-        if (address === undefined)
-          return undefined;
-        return (hexPadding + address.toString(16)).substr(-hexPadding.length);
-      }
-
-      // TODO(petrcermak): This can be quite slow. Consider generating the rows
-      // asynchronously.
-      return this.vmRegions_.map(function(vmRegion) {
-        // The name of the mapped file needs to be handled separately because
-        // the first column must be assigned a fixed size.
+    /**
+     * Classify a memory map and add it as a leaf row to a tree of nested rows.
+     */
+    function classifyVMRegion(row, vmRegion, is64BitAddress) {
+      var rule = row.rule;
+      if (rule === undefined ||
+          rule.children === undefined ||
+          rule.children.length === 0) {
+        // Leaf rule (create a sub-row for the mmap).
         var mappedFile = vmRegion.mappedFile || '';
 
         var cells = {};
@@ -120,49 +217,190 @@
           if (value === undefined)
             return;
           var attr = new attrClass(units, value);
-          var cell = new tv.c.analysis.MemoryCell(attr);
+          var cell = new tr.c.analysis.MemoryCell(attr);
           cells[columnName] = cell;
         }
-        addCellIfValueDefined('Start address',
-            tv.c.trace_model.StringAttribute, '',
-            hexString(vmRegion.startAddress));
-        addCellIfValueDefined('Virtual size',
-            tv.c.trace_model.ScalarAttribute, 'bytes', vmRegion.sizeInBytes);
-        addCellIfValueDefined('Protection flags',
-            tv.c.trace_model.StringAttribute, '',
-            vmRegion.protectionFlagsToString);
-        addCellIfValueDefined('Proportional resident',
-            tv.c.trace_model.ScalarAttribute, 'bytes',
-            vmRegion.byteStats.proportionalResident);
-        addCellIfValueDefined('Private resident',
-            tv.c.trace_model.ScalarAttribute, 'bytes',
-            vmRegion.byteStats.privateResident);
-        addCellIfValueDefined('Shared resident',
-            tv.c.trace_model.ScalarAttribute, 'bytes',
-            vmRegion.byteStats.sharedResident);
-
-        return {mappedFile: mappedFile, cells: cells};
-      });
-    },
-
-    createColumns_: function(rows) {
-      var titleColumn = {
-        title: 'Mapped file',
-        value: function(row) {
-          return row.mappedFile;
-        },
-        width: '200px',
-        cmp: function(rowA, rowB) {
-          return rowA.mappedFile.localeCompare(rowB.mappedFile);
+        function addBytesCellIfValueDefined(columnName, value) {
+          addCellIfValueDefined(columnName,
+              tr.model.ScalarAttribute, 'bytes', value);
         }
-      };
+        addCellIfValueDefined('Start address',
+            tr.model.StringAttribute, '',
+            hexString(vmRegion.startAddress, is64BitAddress));
+        addBytesCellIfValueDefined('Virtual size', vmRegion.sizeInBytes);
+        addCellIfValueDefined('Protection flags',
+            tr.model.StringAttribute, '',
+            vmRegion.protectionFlagsToString);
+        addBytesCellIfValueDefined('PSS',
+            vmRegion.byteStats.proportionalResident);
+        addBytesCellIfValueDefined('Private dirty',
+            vmRegion.byteStats.privateDirtyResident);
+        addBytesCellIfValueDefined('Private clean',
+            vmRegion.byteStats.privateCleanResident);
+        addBytesCellIfValueDefined('Shared dirty',
+            vmRegion.byteStats.sharedDirtyResident);
+        addBytesCellIfValueDefined('Shared clean',
+            vmRegion.byteStats.sharedCleanResident);
+        addBytesCellIfValueDefined('Swapped',
+            vmRegion.byteStats.swapped);
 
-      var attributeColumns = tv.c.analysis.MemoryColumn.fromRows(rows, 'cells');
-      tv.c.analysis.MemoryColumn.spaceEqually(attributeColumns);
+        row.subRows.push({title: mappedFile, cells: cells});
+        return;
+      }
 
-      var columns = [titleColumn].concat(attributeColumns);
-      return columns;
+      // Non-leaf rule (classify mmap further down the tree).
+      function vmRegionMatchesChildRule(childRule) {
+        var fileRegExp = childRule.file;
+        if (fileRegExp === undefined)
+          return true;
+        return fileRegExp.test(vmRegion.mappedFile);
+      }
+
+      var matchedChildRuleIndex = tr.b.findFirstIndexInArray(
+          rule.children, vmRegionMatchesChildRule);
+      if (matchedChildRuleIndex === -1) {
+        // Mmap belongs to the 'Other' node (created lazily).
+        matchedChildRuleIndex = rule.children.length;
+        if (matchedChildRuleIndex >= row.subRows.length) {
+          row.subRows.push({
+            title: 'Other',
+            cells: {},
+            subRows: []
+          });
+        }
+      }
+
+      classifyVMRegion(
+          row.subRows[matchedChildRuleIndex], vmRegion, is64BitAddress);
     }
-  });
+
+    /**
+     * Sum mmap sizes up the classification tree.
+     *
+     * Note that classes containing no memory maps will have no sizes (shown
+     * as empty cells) instead of zeros.
+     */
+    // TODO(petrcermak): This code is almost the same as
+    // MemoryAllocatorDump.aggregateAttributes. Consider sharing code between
+    // the two functions.
+    function aggregateRowCells(row) {
+      if (row.subRows === undefined)
+        return;
+
+      var cells = {};
+
+      row.subRows.forEach(function(subRow) {
+        aggregateRowCells(subRow);
+        tr.b.iterItems(subRow.cells, function(columnName) {
+          cells[columnName] = true;
+        });
+      });
+
+      tr.b.iterItems(cells, function(name) {
+        var childAttributes = row.subRows.map(function(subRow) {
+          var cell = subRow.cells[name];
+          if (cell === undefined)
+            return undefined;
+          return cell.attr;
+        }, this);
+        row.cells[name] = new tr.c.analysis.MemoryCell(
+            tr.model.Attribute.aggregate(childAttributes));
+      });
+    }
+
+    Polymer({
+      // TODO(petrcermak): Consider sharing more code between
+      // tr-c-a-memory-dump-allocator-details-pane and
+      // tr-c-a-memory-dump-vm-regions-details-pane (e.g. by defining a common
+      // base class tr-c-memory-dump-details-pane).
+
+      created: function() {
+        this.vmRegions_ = undefined;
+      },
+
+      ready: function() {
+        this.updateContents_();
+      },
+
+      set vmRegions(vmRegions) {
+        this.vmRegions_ = vmRegions;
+        this.updateContents_();
+      },
+
+      get vmRegions() {
+        return this.vmRegions_;
+      },
+
+      updateContents_: function() {
+        this.$.contents.textContent = '';
+
+        if (this.vmRegions_ === undefined) {
+          var infoText = this.ownerDocument.createElement('div');
+          this.$.contents.appendChild(infoText);
+          infoText.classList.add('info-text');
+          infoText.innerText = 'No memory maps selected';
+          return;
+        }
+
+        var rows = this.createRows_();
+        var columns = this.createColumns_(rows);
+
+        var table = this.ownerDocument.createElement(
+            'tr-b-ui-table');
+        this.$.contents.appendChild(table);
+        table.supportsSelection = true;
+        table.tableRows = rows;
+        table.tableColumns = columns;
+
+        // TODO(petrcermak): This can be quite slow. Consider doing this somehow
+        // asynchronously.
+        table.rebuild();
+
+        tr.c.analysis.expandTableRowsRecursively(table);
+      },
+
+      createRows_: function() {
+        // TODO(petrcermak): Figure out if there's a cleaner way to do this.
+        var is64BitAddress = this.vmRegions_.some(function(vmRegion) {
+          if (vmRegion.startAddress === undefined)
+            return;
+          return vmRegion.startAddress >= 4294967296 /* 2^32 */;
+        });
+
+        // Create an empty tree structure of rows.
+        var rootRow = createEmptyRow(CLASSIFICATION_RULES);
+
+        // Classify the mmaps.
+        this.vmRegions_.map(function(vmRegion) {
+          classifyVMRegion(rootRow, vmRegion, is64BitAddress);
+        });
+
+        // Aggregate attributes of the mmaps.
+        aggregateRowCells(rootRow);
+
+        return [rootRow];
+      },
+
+      createColumns_: function(rows) {
+        var titleColumn = {
+          title: 'Mapped file',
+          value: function(row) {
+            return row.title;
+          },
+          width: '200px',
+          cmp: function(rowA, rowB) {
+            return rowA.title.localeCompare(rowB.title);
+          }
+        };
+
+        var attributeColumns = tr.c.analysis.MemoryColumn.fromRows(
+            rows, 'cells');
+        tr.c.analysis.MemoryColumn.spaceEqually(attributeColumns);
+
+        var columns = [titleColumn].concat(attributeColumns);
+        return columns;
+      }
+    });
+  })();
   </script>
 </polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane_test.html b/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane_test.html
index c1d780e..b121d2e 100644
--- a/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/memory_dump_vm_regions_details_pane_test.html
@@ -9,21 +9,21 @@
 <link rel="import"
     href="/core/analysis/memory_dump_vm_regions_details_pane.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/process_memory_dump.html">
+<link rel="import" href="/model/process_memory_dump.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var VMRegion = tv.c.trace_model.VMRegion;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var VMRegion = tr.model.VMRegion;
 
   function createVMRegions() {
     return [
       VMRegion.fromDict({
         mappedFile: '/lib/chrome.so',
         startAddress: 65536,
-        sizeInBytes: 2097152,
+        sizeInBytes: 536870912,
         protectionFlags: VMRegion.PROTECTION_FLAG_READ |
             VMRegion.PROTECTION_FLAG_EXECUTE,
         byteStats: {
@@ -32,20 +32,37 @@
       }),
       VMRegion.fromDict({
         startAddress: 10995116277760,
-        sizeInBytes: 4294967296,
+        sizeInBytes: 2147483648,
         protectionFlags: VMRegion.PROTECTION_FLAG_READ |
             VMRegion.PROTECTION_FLAG_WRITE,
         byteStats: {
-          privateResident: 0,
-          sharedResident: 0
+          privateDirtyResident: 0,
+          swapped: 0
+        }
+      }),
+      VMRegion.fromDict({
+        startAddress: 12094627905536,
+        sizeInBytes: 2147483648,
+        protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+            VMRegion.PROTECTION_FLAG_WRITE,
+        byteStats: {
+          privateDirtyResident: 0,
+          swapped: 0
         }
       })
     ];
   }
 
+  function checkRowValue(row, column, expectedValue) {
+    var value = column.value(row);
+    if (typeof(expectedValue) === 'number')
+      value = value.numBytes;
+    assert.equal(value, expectedValue);
+  }
+
   test('instantiate_empty', function() {
     var viewEl = document.createElement(
-        'tv-c-memory-dump-vm-regions-details-pane');
+        'tr-c-a-memory-dump-vm-regions-details-pane');
     this.addHTMLOutput(viewEl);
   });
 
@@ -53,42 +70,79 @@
     var vmRegions = createVMRegions();
 
     var viewEl = document.createElement(
-        'tv-c-memory-dump-vm-regions-details-pane');
+        'tr-c-a-memory-dump-vm-regions-details-pane');
     viewEl.vmRegions = vmRegions;
     this.addHTMLOutput(viewEl);
 
-    var table = tv.b.findDeepElementMatching(
-        viewEl, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        viewEl, 'tr-b-ui-table');
 
-    var rows = table.tableRows;
     var columns = table.tableColumns;
-    assert.lengthOf(rows, 2);
-    assert.lengthOf(columns, 7);
 
-    var mappedFileColumn = columns[0];
-    var startAddressColumn = columns[1];
-    var virtualSizeColumn = columns[2];
-    var protectionFlagsColumn = columns[3];
-    var proportionalResidentColumn = columns[4];
-    var privateResidentColumn = columns[5];
-    var sharedResidentColumn = columns[6];
+    assert.lengthOf(columns, 7);
+    var titleColumn = columns[0];
+    var virtualSizeColumn = columns[1];
+    var proportionalResidentColumn = columns[2];
+    var privateDirtyResidentColumn = columns[3];
+    var swappedColumn = columns[4];
+    var startAddressColumn = columns[5];
+    var protectionFlagsColumn = columns[6];
+
+    function checkRow(row, expectedTitle, expectedVirtualSize,
+        expectedProportionalResident, expectedPrivateDirtyResident,
+        expectedSwapped, expectedStartAddress, expectedProtectionFlags,
+        expectedSubRowCount) {
+      checkRowValue(row, titleColumn, expectedTitle);
+      checkRowValue(row, virtualSizeColumn, expectedVirtualSize);
+      checkRowValue(
+          row, proportionalResidentColumn, expectedProportionalResident);
+      checkRowValue(
+          row, privateDirtyResidentColumn, expectedPrivateDirtyResident);
+      checkRowValue(row, swappedColumn, expectedSwapped);
+      checkRowValue(row, startAddressColumn, expectedStartAddress);
+      checkRowValue(row, protectionFlagsColumn, expectedProtectionFlags);
+
+      if (expectedSubRowCount === undefined)
+        assert.isUndefined(row.subRows);
+      else
+        assert.lengthOf(row.subRows, expectedSubRowCount);
+    }
 
     // Check the rows of the table.
-    assert.equal(mappedFileColumn.value(rows[0]), '/lib/chrome.so');
-    assert.equal(startAddressColumn.value(rows[0]), '0000000000010000');
-    assert.equal(virtualSizeColumn.value(rows[0]).numBytes, 2097152);
-    assert.equal(protectionFlagsColumn.value(rows[0]), 'r-x');
-    assert.equal(proportionalResidentColumn.value(rows[0]).numBytes, 8192);
-    assert.equal(privateResidentColumn.value(rows[0]), '');
-    assert.equal(sharedResidentColumn.value(rows[0]), '');
+    var rows = table.tableRows;
+    assert.lengthOf(rows, 1);
 
-    assert.equal(mappedFileColumn.value(rows[1]), '');
-    assert.equal(startAddressColumn.value(rows[1]), '00000a0000000000');
-    assert.equal(virtualSizeColumn.value(rows[1]).numBytes, 4294967296);
-    assert.equal(protectionFlagsColumn.value(rows[1]), 'rw-');
-    assert.equal(proportionalResidentColumn.value(rows[1]), '');
-    assert.equal(privateResidentColumn.value(rows[1]).numBytes, 0);
-    assert.equal(sharedResidentColumn.value(rows[1]).numBytes, 0);
+    var totalRow = rows[0];
+    checkRow(totalRow, 'Total', 4831838208, 8192, 0, 0, '', '', 7);
+
+    var androidRow = totalRow.subRows[0];
+    checkRow(androidRow, 'Android', '', '', '', '', '', '', 3);
+
+    var javaRuntimeRow = androidRow.subRows[0];
+    checkRow(javaRuntimeRow, 'Java runtime', '', '', '', '', '', '', 5);
+
+    var spacesRow = javaRuntimeRow.subRows[0];
+    checkRow(spacesRow, 'Spaces', '', '', '', '', '', '', 4);
+
+    var normalRow = spacesRow.subRows[0];
+    checkRow(normalRow, 'Normal', '', '', '', '', '', '', 0);
+
+    var filesRow = totalRow.subRows[3];
+    checkRow(filesRow, 'Files', 536870912, 8192, '', '', '', '', 7);
+
+    var soRow = filesRow.subRows[0];
+    checkRow(soRow, 'so', 536870912, 8192, '', '', '', '', 1);
+
+    var mmapChromeRow = soRow.subRows[0];
+    checkRow(mmapChromeRow, '/lib/chrome.so', 536870912, 8192, '', '',
+        '0000000000010000', 'r-x', undefined);
+
+    var otherRow = totalRow.subRows[6];
+    checkRow(otherRow, 'Other', 4294967296, '', 0, 0, '', '', 2);
+
+    var mmapOther2Row = otherRow.subRows[1];
+    checkRow(mmapOther2Row, '', 2147483648, '', 0, 0, '00000b0000000000',
+        'rw-', undefined);
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_async_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_async_slice_sub_view.html
index 61e56c9..037a2cb 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_async_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_async_slice_sub_view.html
@@ -8,15 +8,15 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 
-<polymer-element name="tv-c-a-multi-async-slice-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-async-slice-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
       display: flex;
     }
     </style>
-    <tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+    <tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
   </template>
 
   <script>
@@ -34,7 +34,7 @@
     get relatedEventsToHighlight() {
       if (!this.currentSelection_)
         return undefined;
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       this.currentSelection_.forEach(function(asyncEvent) {
         if (!asyncEvent.associatedEvents)
           return;
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view.html
index dd1548f..e43371a 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 
-<polymer-element name="tv-c-a-multi-cpu-slice-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-cpu-slice-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -19,7 +19,7 @@
       flex: 1 1 auto;
     }
     </style>
-    <tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+    <tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
   </template>
 
   <script>
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view_test.html
index e4b2ab9..797056a 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_cpu_slice_sub_view_test.html
@@ -8,13 +8,13 @@
 <link rel="import" href="/core/analysis/multi_cpu_slice_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function createBasicModel() {
     var lines = [
       'Android.launcher-584   [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
@@ -26,7 +26,7 @@
       '       Binder_1-217   [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
     ];
 
-    return new tv.c.TraceModel(lines.join('\n'), false);
+    return new tr.Model(lines.join('\n'), false);
   }
 
   test('instantiate', function() {
@@ -34,11 +34,11 @@
     var cpu = m.kernel.cpus[1];
     assert.isDefined(cpu);
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(cpu.slices[0]);
     selection.push(cpu.slices[1]);
 
-    var viewEl = document.createElement('tv-c-a-multi-cpu-slice-sub-view');
+    var viewEl = document.createElement('tr-c-a-multi-cpu-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_details_table.html b/trace-viewer/trace_viewer/core/analysis/multi_event_details_table.html
index 52e5f26..905a655 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_details_table.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_details_table.html
@@ -6,13 +6,13 @@
 -->
 
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 <link rel="import" href="/core/analysis/multi_event_summary.html">
-<link rel="import" href="/core/analysis/time_span.html">
-<link rel="import" href="/core/analysis/time_stamp.html">
+<link rel="import" href="/base/units/time_duration_span.html">
+<link rel="import" href="/base/units/time_stamp_span.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
 
-<polymer-element name='tv-c-a-multi-event-details-table'>
+<polymer-element name='tr-c-a-multi-event-details-table'>
   <template>
     <style>
     :host {
@@ -32,10 +32,10 @@
       font-size: 12px;
     }
     </style>
-    <tracing-analysis-nested-table id="titletable">
-    </tracing-analysis-nested-table>
-    <tracing-analysis-nested-table id="table">
-    </tracing-analysis-nested-table>
+    <tr-b-ui-table id="titletable">
+    </tr-b-ui-table>
+    <tr-b-ui-table id="table">
+    </tr-b-ui-table>
   </template>
 
   <script>
@@ -91,7 +91,7 @@
         return;
       }
 
-      var summary = new tv.c.analysis.MultiEventSummary(
+      var summary = new tr.c.analysis.MultiEventSummary(
           'Totals', this.selection_);
       this.updateColumns_(summary);
       this.updateRows_(summary);
@@ -150,15 +150,15 @@
       columns.push({
         title: 'Start',
         value: function(row) {
-          if (row.__proto__ === tv.c.analysis.MultiEventSummary.prototype) {
+          if (row.__proto__ === tr.c.analysis.MultiEventSummary.prototype) {
             return row.title;
           }
 
-          var linkEl = document.createElement('tv-c-analysis-link');
+          var linkEl = document.createElement('tr-c-a-analysis-link');
           linkEl.setSelectionAndContent(function() {
-              return new tv.c.Selection(row.event);
+              return new tr.c.Selection(row.event);
           });
-          linkEl.appendChild(tv.c.analysis.createTimeStamp(row.start));
+          linkEl.appendChild(tr.b.units.createTimeStampSpan(row.start));
           return linkEl;
         },
         width: '350px',
@@ -171,7 +171,7 @@
         columns.push({
           title: 'Wall Duration (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.duration);
+            return tr.b.units.createTimeSpan(row.duration);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -184,7 +184,7 @@
         columns.push({
           title: 'CPU Duration (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.cpuDuration);
+            return tr.b.units.createTimeSpan(row.cpuDuration);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -197,7 +197,7 @@
         columns.push({
           title: 'Self time (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.selfTime);
+            return tr.b.units.createTimeSpan(row.selfTime);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -210,7 +210,7 @@
         columns.push({
           title: 'CPU Self Time (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.cpuSelfTime);
+            return tr.b.units.createTimeSpan(row.cpuSelfTime);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -219,7 +219,7 @@
         });
       }
 
-      var argKeys = tv.b.dictionaryKeys(summary.totalledArgs);
+      var argKeys = tr.b.dictionaryKeys(summary.totalledArgs);
       argKeys.sort();
 
       var otherKeys = summary.untotallableArgs.slice(0);
@@ -235,9 +235,9 @@
         var colDesc = {
           title: 'Arg: ' + argKey,
           value: function(row) {
-            if (row.__proto__ !== tv.c.analysis.MultiEventSummary.prototype) {
+            if (row.__proto__ !== tr.c.analysis.MultiEventSummary.prototype) {
               var argView =
-                  document.createElement('tv-c-analysis-generic-object-view');
+                  document.createElement('tr-c-a-generic-object-view');
               argView.object = row.args[argKey];
               return argView;
             }
@@ -259,10 +259,10 @@
         columns.push({
           title: 'Other Args',
           value: function(row) {
-            if (row.__proto__ === tv.c.analysis.MultiEventSummary.prototype)
+            if (row.__proto__ === tr.c.analysis.MultiEventSummary.prototype)
               return '';
             var argView =
-                document.createElement('tv-c-analysis-generic-object-view');
+                document.createElement('tr-c-a-generic-object-view');
             var obj = {};
             for (var i = 0; i < keysInOtherColumn.length; i++)
               obj[keysInOtherColumn[i]] = row.args[keysInOtherColumn[i]];
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_details_table_test.html b/trace-viewer/trace_viewer/core/analysis/multi_event_details_table_test.html
index c5b2e61..09da972 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_details_table_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_details_table_test.html
@@ -9,16 +9,16 @@
 <link rel="import" href="/core/analysis/multi_event_details_table.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Thread = tv.c.trace_model.Thread;
-  var Selection = tv.c.Selection;
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Thread = tr.model.Thread;
+  var Selection = tr.c.Selection;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
   test('sortingOfFirstColumn', function() {
     var model = new Model();
@@ -37,7 +37,7 @@
 
     var selection = new Selection(tsg.slices);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-details-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-details-table');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
 
@@ -63,7 +63,7 @@
 
     var selection = new Selection(tsg.slices);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-details-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-details-table');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
@@ -82,7 +82,7 @@
 
     var selection = new Selection(tsg.slices);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-details-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-details-table');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
@@ -105,7 +105,7 @@
 
     var selection = new Selection(tsg.slices);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-details-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-details-table');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
@@ -130,7 +130,7 @@
 
     var selection = new Selection(tsg.slices);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-details-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-details-table');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
@@ -138,8 +138,8 @@
   test('noDuration', function() {
     var model = new Model();
 
-    var fe1 = new tv.c.trace_model.FlowEvent('cat', 1234, 'title', 7, 10, {});
-    var fe2 = new tv.c.trace_model.FlowEvent('cat', 1234, 'title', 8, 20, {});
+    var fe1 = new tr.model.FlowEvent('cat', 1234, 'title', 7, 10, {});
+    var fe2 = new tr.model.FlowEvent('cat', 1234, 'title', 8, 20, {});
 
     // Make reading some properties an explosion, as a way to ensure that they
     // aren't read.
@@ -162,7 +162,7 @@
 
     var selection = new Selection([fe1, fe2]);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-details-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-details-table');
     viewEl.eventsHaveDuration = false;
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view.html
index c70db33..81709ce 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view.html
@@ -11,10 +11,10 @@
 <link rel="import" href="/core/analysis/selection_summary_table.html">
 <link rel="import" href="/core/analysis/multi_event_summary_table.html">
 <link rel="import" href="/core/analysis/multi_event_details_table.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 
-<polymer-element name="tv-c-a-multi-event-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-event-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -31,11 +31,11 @@
       flex: 0 0 auto;
       align-self: stretch;
     }
-    tv-c-a-multi-event-summary-table {
+    tr-c-a-multi-event-summary-table {
       border-bottom: 1px solid #aaa;
     }
 
-    tv-c-a-selection-summary-table  {
+    tr-c-a-selection-summary-table  {
       margin-top: 1.25em;
       border-top: 1px solid #aaa;
       background-color: #eee;
@@ -97,10 +97,10 @@
         return;
 
       var eventsByTitle = selection.getEventsOrganizedByTitle();
-      var numTitles = tv.b.dictionaryLength(eventsByTitle);
+      var numTitles = tr.b.dictionaryLength(eventsByTitle);
 
       var summaryTableEl = document.createElement(
-          'tv-c-a-multi-event-summary-table');
+          'tr-c-a-multi-event-summary-table');
       summaryTableEl.configure({
         showTotals: numTitles > 1,
         eventsByTitle: eventsByTitle,
@@ -110,13 +110,13 @@
       this.$.content.appendChild(summaryTableEl);
 
       var selectionSummaryTableEl = document.createElement(
-          'tv-c-a-selection-summary-table');
+          'tr-c-a-selection-summary-table');
       selectionSummaryTableEl.selection = this.currentSelection_;
       this.$.content.appendChild(selectionSummaryTableEl);
 
       if (numTitles === 1) {
         var detailsTableEl = document.createElement(
-            'tv-c-a-multi-event-details-table');
+            'tr-c-a-multi-event-details-table');
         detailsTableEl.eventsHaveDuration = this.eventsHaveDuration_;
         detailsTableEl.eventsHaveSubRows = this.eventsHaveSubRows_;
         detailsTableEl.selection = selection;
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view_test.html
index d936e8f..327de44 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_sub_view_test.html
@@ -9,18 +9,18 @@
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Thread = tv.c.trace_model.Thread;
-  var Selection = tv.c.Selection;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-  var newSliceCategory = tv.c.test_utils.newSliceCategory;
-  var Slice = tv.c.trace_model.Slice;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Thread = tr.model.Thread;
+  var Selection = tr.c.Selection;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+  var newSliceCategory = tr.c.test_utils.newSliceCategory;
+  var Slice = tr.model.Slice;
 
   test('differentTitles', function() {
     var model = new Model();
@@ -38,24 +38,24 @@
     selection.push(t53.sliceGroup.slices[1]);
     selection.push(t53.sliceGroup.slices[2]);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-sub-view');
+    var viewEl = document.createElement('tr-c-a-multi-event-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
 
-    var summaryTableEl = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-a-multi-event-summary-table');
+    var summaryTableEl = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-multi-event-summary-table');
     assert.isDefined(summaryTableEl);
 
     assert.isTrue(summaryTableEl.showTotals);
-    assert.equal(tv.b.dictionaryLength(summaryTableEl.eventsByTitle), 2);
+    assert.equal(tr.b.dictionaryLength(summaryTableEl.eventsByTitle), 2);
 
-    var selectionSummaryTableEl = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-a-selection-summary-table');
+    var selectionSummaryTableEl = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-selection-summary-table');
     assert.isDefined(selectionSummaryTableEl);
     assert.equal(selectionSummaryTableEl.selection, selection);
 
-    var detailsTableEl = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-a-multi-event-details-table');
+    var detailsTableEl = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-multi-event-details-table');
     assert.isUndefined(detailsTableEl);
   });
 
@@ -73,24 +73,24 @@
     selection.push(t53.sliceGroup.slices[0]);
     selection.push(t53.sliceGroup.slices[1]);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-sub-view');
+    var viewEl = document.createElement('tr-c-a-multi-event-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
 
-    var summaryTableEl = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-a-multi-event-summary-table');
+    var summaryTableEl = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-multi-event-summary-table');
     assert.isDefined(summaryTableEl);
 
     assert.isFalse(summaryTableEl.showTotals);
-    assert.equal(tv.b.dictionaryLength(summaryTableEl.eventsByTitle), 1);
+    assert.equal(tr.b.dictionaryLength(summaryTableEl.eventsByTitle), 1);
 
-    var selectionSummaryTableEl = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-a-selection-summary-table');
+    var selectionSummaryTableEl = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-selection-summary-table');
     assert.isDefined(selectionSummaryTableEl);
     assert.equal(selectionSummaryTableEl.selection, selection);
 
-    var detailsTableEl = tv.b.findDeepElementMatching(
-        viewEl, 'tv-c-a-multi-event-details-table');
+    var detailsTableEl = tr.b.findDeepElementMatching(
+        viewEl, 'tr-c-a-multi-event-details-table');
         assert.isDefined(detailsTableEl);
     assert.equal(detailsTableEl.selection, selection);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_summary.html b/trace-viewer/trace_viewer/core/analysis/multi_event_summary.html
index c2599e9..d796936 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_summary.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_summary.html
@@ -11,7 +11,7 @@
 
 <script>
 'use strict';
-tv.exportTo('tv.c.analysis', function() {
+tr.exportTo('tr.c.analysis', function() {
   function MultiEventSummary(title, events) {
     this.title = title;
     this.duration_ = undefined;
@@ -28,7 +28,7 @@
   MultiEventSummary.prototype = {
     get duration() {
       if (this.duration_ === undefined) {
-        this.duration_ = tv.b.Statistics.sum(
+        this.duration_ = tr.b.Statistics.sum(
             this.events_, function(event) {
                 return event.duration;
             });
@@ -93,7 +93,7 @@
 
     get numAlerts() {
       if (this.numAlerts_ === undefined) {
-        this.numAlerts_ = tv.b.Statistics.sum(this.events_, function(event) {
+        this.numAlerts_ = tr.b.Statistics.sum(this.events_, function(event) {
           return event.associatedAlerts.length;
         });
       }
@@ -135,7 +135,7 @@
           totalledArgs[argName] += argVal;
         }
       }
-      this.untotallableArgs_ = tv.b.dictionaryKeys(untotallableArgs);
+      this.untotallableArgs_ = tr.b.dictionaryKeys(untotallableArgs);
       this.totalledArgs_ = totalledArgs;
     }
   };
@@ -144,4 +144,4 @@
     MultiEventSummary: MultiEventSummary
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table.html b/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table.html
index fadba05..1ec283c 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table.html
@@ -10,11 +10,11 @@
 <link rel="import" href="/base/statistics.html">
 <link rel="import" href="/core/analysis/analysis_link.html">
 <link rel="import" href="/core/analysis/multi_event_summary.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/analysis/time_span.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/units/time_duration_span.html">
 
 </script>
-<polymer-element name='tv-c-a-multi-event-summary-table'>
+<polymer-element name='tr-c-a-multi-event-summary-table'>
   <template>
     <style>
     :host {
@@ -25,8 +25,8 @@
       align-self: stretch;
     }
     </style>
-    <tracing-analysis-nested-table id="table">
-    </tracing-analysis-nested-table>
+    <tr-b-ui-table id="table">
+    </tr-b-ui-table>
     </div>
   </template>
   <script>
@@ -61,9 +61,9 @@
           if (row.title === 'Totals')
             return 'Totals';
 
-          var linkEl = document.createElement('tv-c-analysis-link');
+          var linkEl = document.createElement('tr-c-a-analysis-link');
           linkEl.setSelectionAndContent(function() {
-            return new tv.c.Selection(row.events);
+            return new tr.c.Selection(row.events);
           }, row.title);
           return linkEl;
         },
@@ -76,7 +76,7 @@
         columns.push({
           title: 'Wall Duration (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.duration);
+            return tr.b.units.createTimeSpan(row.duration);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -89,7 +89,7 @@
         columns.push({
           title: 'CPU Duration (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.cpuDuration);
+            return tr.b.units.createTimeSpan(row.cpuDuration);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -102,7 +102,7 @@
         columns.push({
           title: 'Self time (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.selfTime);
+            return tr.b.units.createTimeSpan(row.selfTime);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -115,7 +115,7 @@
         columns.push({
           title: 'CPU Self Time (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.cpuSelfTime);
+            return tr.b.units.createTimeSpan(row.cpuSelfTime);
           },
           width: '<upated further down>',
           cmp: function(rowA, rowB) {
@@ -242,11 +242,11 @@
 
       var allEvents = [];
       var rows = [];
-      tv.b.iterItems(
+      tr.b.iterItems(
           eventsByTitle,
           function(title, eventsOfSingleTitle) {
             allEvents.push.apply(allEvents, eventsOfSingleTitle);
-            var row = new tv.c.analysis.MultiEventSummary(title,
+            var row = new tr.c.analysis.MultiEventSummary(title,
                                                           eventsOfSingleTitle);
             rows.push(row);
           });
@@ -258,7 +258,7 @@
 
       if (this.showTotals_) {
         footerRows.push(
-            new tv.c.analysis.MultiEventSummary('Totals', allEvents));
+            new tr.c.analysis.MultiEventSummary('Totals', allEvents));
       }
       // TODO(selection bounds).
 
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table_test.html b/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table_test.html
index b94315b..951efa9 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_summary_table_test.html
@@ -9,15 +9,15 @@
 <link rel="import" href="/core/analysis/multi_event_summary_table.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
   test('basicNoCpu', function() {
     var model = new Model();
@@ -33,7 +33,7 @@
 
     var selection = new Selection(tsg.slices);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-summary-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-summary-table');
     viewEl.configure({
       showTotals: true,
       eventsHaveDuration: true,
@@ -59,7 +59,7 @@
 
     var selection = new Selection(tsg.slices);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-summary-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-summary-table');
     viewEl.configure({
       showTotals: true,
       eventsHaveDuration: true,
@@ -71,8 +71,8 @@
   test('noDurationNoSubRows', function() {
     var model = new Model();
 
-    var fe1 = new tv.c.trace_model.FlowEvent('cat', 1234, 'title', 7, 10, {});
-    var fe2 = new tv.c.trace_model.FlowEvent('cat', 1234, 'title', 8, 20, {});
+    var fe1 = new tr.model.FlowEvent('cat', 1234, 'title', 7, 10, {});
+    var fe2 = new tr.model.FlowEvent('cat', 1234, 'title', 8, 20, {});
 
     // Make reading some properties an explosion, as a way to ensure that they
     // aren't read.
@@ -95,7 +95,7 @@
 
     var selection = new Selection([fe1, fe2]);
 
-    var viewEl = document.createElement('tv-c-a-multi-event-summary-table');
+    var viewEl = document.createElement('tr-c-a-multi-event-summary-table');
     viewEl.configure({
       showTotals: true,
       eventsHaveDuration: false,
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_event_summary_test.html b/trace-viewer/trace_viewer/core/analysis/multi_event_summary_test.html
index 7e3635b..a6f997f 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_event_summary_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_event_summary_test.html
@@ -8,15 +8,15 @@
 <link rel="import" href="/core/analysis/multi_event_summary.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
   test('summaryRowNoCpu', function() {
     var model = new Model();
@@ -28,7 +28,7 @@
     tsg.pushSlice(newSliceEx({title: 'bb', start: 4, end: 5}));
     tsg.createSubSlices();
 
-    var row = new tv.c.analysis.MultiEventSummary('x', tsg.slices.slice(0));
+    var row = new tr.c.analysis.MultiEventSummary('x', tsg.slices.slice(0));
     assert.equal(row.duration, 5);
     assert.equal(row.selfTime, 4);
     assert.isUndefined(row.cpuDuration);
@@ -48,7 +48,7 @@
                               cpuStart: 3, cpuEnd: 3.75}));
     tsg.createSubSlices();
 
-    var row = new tv.c.analysis.MultiEventSummary('x', tsg.slices.slice(0));
+    var row = new tr.c.analysis.MultiEventSummary('x', tsg.slices.slice(0));
     assert.equal(row.duration, 5);
     assert.equal(row.selfTime, 4);
     assert.equal(row.cpuDuration, 4.5);
@@ -60,12 +60,12 @@
     var thread = model.getOrCreateProcess(1).getOrCreateThread(2);
     var tsg = thread.sliceGroup;
 
-    var fe1 = new tv.c.trace_model.FlowEvent('cat', 1234, 'title', 7, 10, {});
-    var fe2 = new tv.c.trace_model.FlowEvent('cat', 1234, 'title', 8, 20, {});
+    var fe1 = new tr.model.FlowEvent('cat', 1234, 'title', 7, 10, {});
+    var fe2 = new tr.model.FlowEvent('cat', 1234, 'title', 8, 20, {});
     model.flowEvents.push(fe1);
     model.flowEvents.push(fe2);
 
-    var row = new tv.c.analysis.MultiEventSummary('a', [fe1, fe2]);
+    var row = new tr.c.analysis.MultiEventSummary('a', [fe1, fe2]);
     assert.equal(row.duration, 0);
     assert.equal(row.selfTime, 0);
     assert.isUndefined(row.cpuDuration);
@@ -75,12 +75,12 @@
   test('summaryNumAlerts', function() {
     var slice = newSliceEx({title: 'b', start: 0, duration: 0.002});
 
-    var ALERT_INFO_1 = new tv.c.trace_model.EventInfo(
+    var ALERT_INFO_1 = new tr.model.EventInfo(
         'Alert 1', 'Critical alert');
 
-    var alert = new tv.c.trace_model.Alert(ALERT_INFO_1, 5, [slice]);
+    var alert = new tr.model.Alert(ALERT_INFO_1, 5, [slice]);
 
-    var row = new tv.c.analysis.MultiEventSummary('a', [slice]);
+    var row = new tr.c.analysis.MultiEventSummary('a', [slice]);
     assert.equal(row.numAlerts, 1);
   });
 
@@ -97,7 +97,7 @@
                               args: {value1: 3, value2: 'z', value3: 'x'}}));
     tsg.createSubSlices();
 
-    var row = new tv.c.analysis.MultiEventSummary('x', tsg.slices.slice(0));
+    var row = new tr.c.analysis.MultiEventSummary('x', tsg.slices.slice(0));
     assert.deepEqual(row.totalledArgs, {value1: 9});
     assert.deepEqual(row.untotallableArgs, ['value2', 'value3']);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view.html
index 910dc6b..5a7935d 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view.html
@@ -8,15 +8,15 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 
-<polymer-element name="tv-c-multi-flow-event-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-flow-event-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
       display: flex;
     }
     </style>
-    <tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+    <tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
   </template>
 
   <script>
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view_test.html
index f4ddca9..c2bcab7 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_flow_event_sub_view_test.html
@@ -8,21 +8,20 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var trace_model = tv.c.trace_model;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
 
   test('analyzeSelectionWithSingleEvent', function() {
     var model = new Model();
 
-    var fe1 = new trace_model.FlowEvent('cat', 1234, 'title', 7, 10, {});
-    var fe2 = new trace_model.FlowEvent('cat', 1234, 'title', 8, 20, {});
+    var fe1 = new tr.model.FlowEvent('cat', 1234, 'title', 7, 10, {});
+    var fe2 = new tr.model.FlowEvent('cat', 1234, 'title', 8, 20, {});
     model.flowEvents.push(fe1);
     model.flowEvents.push(fe2);
 
@@ -31,7 +30,7 @@
     selection.push(fe2);
     assert.equal(selection.length, 2);
 
-    var subView = document.createElement('tv-c-multi-flow-event-sub-view');
+    var subView = document.createElement('tr-c-a-multi-flow-event-sub-view');
     subView.selection = selection;
 
     this.addHTMLOutput(subView);
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_frame_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_frame_sub_view.html
index 46be455..9a62241 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_frame_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_frame_sub_view.html
@@ -7,10 +7,10 @@
 
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
-<polymer-element name="tv-c-multi-frame-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-frame-sub-view"
+    extends="tr-c-a-sub-view">
   <script>
   'use strict';
 
@@ -21,7 +21,7 @@
 
     set selection(selection) {
       this.textContent = '';
-      var realView = document.createElement('tv-c-a-multi-event-sub-view');
+      var realView = document.createElement('tr-c-a-multi-event-sub-view');
       realView.eventsHaveDuration = false;
       realView.eventsHaveSubRows = false;
 
@@ -38,7 +38,7 @@
     get relatedEventsToHighlight() {
       if (!this.currentSelection_)
         return undefined;
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       this.currentSelection_.forEach(function(frameEvent) {
         frameEvent.associatedEvents.forEach(function(event) {
           selection.push(event);
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view.html
index 7abb6a9..38ca97d 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view.html
@@ -6,18 +6,18 @@
 -->
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/units/util.html">
 
-<polymer-element name="tv-c-multi-global-memory-dump-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-global-memory-dump-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
       display: flex;
     }
     </style>
-    <tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+    <tr-b-ui-table id="content"></tr-b-ui-table>
   </template>
 
   <script>
@@ -35,22 +35,22 @@
     set selection(selection) {
       this.currentSelection_ = selection;
 
-      selection = tv.b.asArray(selection).sort(
-          tv.b.Range.compareByMinTimes);
+      selection = tr.b.asArray(selection).sort(
+          tr.b.Range.compareByMinTimes);
 
       var table = this.$.content;
       table.tableColumns = [
         {
           title: 'Dump',
           value: function(row) {
-            var linkEl = document.createElement('tv-c-analysis-link');
+            var linkEl = document.createElement('tr-c-a-analysis-link');
             linkEl.setSelectionAndContent(function() {
-                return new tv.c.Selection(row);
+                return new tr.c.Selection(row);
             });
             var spanEl = document.createElement('span');
             spanEl.textContent = 'Global memory dump at ';
             linkEl.appendChild(spanEl);
-            linkEl.appendChild(tv.c.analysis.createTimeStamp(row.start));
+            linkEl.appendChild(tr.b.units.createTimeStampSpan(row.start));
             return linkEl;
           }
         }
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view_test.html
index 3beea7f..45b4bae 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_global_memory_dump_sub_view_test.html
@@ -8,21 +8,17 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TraceModel = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var GlobalMemoryDump = tv.c.trace_model.GlobalMemoryDump;
-
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
 
     function addGlobalMemoryDump(timestamp) {
-      var gmd = new GlobalMemoryDump(m, timestamp);
+      var gmd = new tr.model.GlobalMemoryDump(m, timestamp);
       m.globalMemoryDumps.push(gmd);
       return gmd;
     }
@@ -30,13 +26,13 @@
     var d1 = addGlobalMemoryDump(5);
     var d2 = addGlobalMemoryDump(20);
 
-    var selection = new Selection();
+    var selection = new tr.c.Selection();
     selection.push(d1);
     selection.push(d2);
     assert.equal(selection.length, 2);
 
     var subView = document.createElement(
-        'tv-c-multi-global-memory-dump-sub-view');
+        'tr-c-a-multi-global-memory-dump-sub-view');
     subView.selection = selection;
 
     this.addHTMLOutput(subView);
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view.html
index 7b65b19..1a05139 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 
-<polymer-element name="tv-c-multi-instant-event-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-instant-event-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -29,7 +29,7 @@
 
     set selection(selection) {
       this.$.content.textContent = '';
-      var realView = document.createElement('tv-c-a-multi-event-sub-view');
+      var realView = document.createElement('tr-c-a-multi-event-sub-view');
       realView.eventsHaveDuration = false;
       realView.eventsHaveSubRows = false;
 
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view_test.html
index 34ea4e3..ac38ff1 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_instant_event_sub_view_test.html
@@ -8,23 +8,22 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var trace_model = tv.c.trace_model;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
 
   test('analyzeSelectionWithSingleEvent', function() {
     var model = new Model();
     var p52 = model.getOrCreateProcess(52);
     var t53 = p52.getOrCreateThread(53);
 
-    var ie1 = new trace_model.ProcessInstantEvent('cat', 'title', 7, 10, {});
-    var ie2 = new trace_model.ProcessInstantEvent('cat', 'title', 7, 20, {});
+    var ie1 = new tr.model.ProcessInstantEvent('cat', 'title', 7, 10, {});
+    var ie2 = new tr.model.ProcessInstantEvent('cat', 'title', 7, 20, {});
     p52.instantEvents.push(ie1);
     p52.instantEvents.push(ie2);
 
@@ -34,7 +33,7 @@
     selection.push(ie2);
     assert.equal(selection.length, 2);
 
-    var subView = document.createElement('tv-c-multi-instant-event-sub-view');
+    var subView = document.createElement('tr-c-a-multi-instant-event-sub-view');
     subView.selection = selection;
 
     this.addHTMLOutput(subView);
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_interaction_record_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_interaction_record_sub_view.html
index 57b989f..71ce76f 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_interaction_record_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_interaction_record_sub_view.html
@@ -7,10 +7,10 @@
 
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
-<polymer-element name="tv-c-multi-interaction-record-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-interaction-record-sub-view"
+    extends="tr-c-a-sub-view">
   <script>
   'use strict';
 
@@ -22,7 +22,7 @@
     set selection(selection) {
       this.currentSelection_ = selection;
       this.textContent = '';
-      var realView = document.createElement('tv-c-a-multi-event-sub-view');
+      var realView = document.createElement('tr-c-a-multi-event-sub-view');
 
       this.appendChild(realView);
       realView.setSelectionWithoutErrorChecks(selection);
@@ -37,7 +37,7 @@
     get relatedEventsToHighlight() {
       if (!this.currentSelection_)
         return undefined;
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       this.currentSelection_.forEach(function(ir) {
         ir.associatedEvents.forEach(function(event) {
           selection.push(event);
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view.html
index c909a9f..6bba864 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view.html
@@ -6,21 +6,21 @@
 -->
 
 <link rel="import" href="/base/ui/dom_helpers.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/analysis/time_stamp.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/units/time_stamp_span.html">
 <link rel="import" href="/core/analysis/analysis_link.html">
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
-<polymer-element name="tv-c-multi-object-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-object-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
       display: flex;
     }
     </style>
-    <tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+    <tr-b-ui-table id="content"></tr-b-ui-table>
   </template>
   <script>
   'use strict';
@@ -41,27 +41,28 @@
     set selection(selection) {
       this.currentSelection_ = selection;
 
-      var objectEvents = tv.b.asArray(selection).sort(
-          tv.b.Range.compareByMinTimes);
+      var objectEvents = tr.b.asArray(selection).sort(
+          tr.b.Range.compareByMinTimes);
 
       var table = this.$.content;
       table.tableColumns = [
         {
           title: 'First',
           value: function(event) {
-            if (event instanceof tv.c.trace_model.ObjectSnapshot)
-              return tv.c.analysis.createTimeStamp(event.ts);
+            if (event instanceof tr.model.ObjectSnapshot)
+              return tr.b.units.createTimeStampSpan(event.ts);
 
             var spanEl = document.createElement('span');
-            spanEl.appendChild(tv.c.analysis.createTimeStamp(event.creationTs));
-            spanEl.appendChild(tv.b.ui.createSpan({
+            spanEl.appendChild(tr.b.units.createTimeStampSpan(
+                event.creationTs));
+            spanEl.appendChild(tr.b.ui.createSpan({
                 textContent: '-',
                 marginLeft: '4px',
                 marginRight: '4px'
             }));
             if (event.deletionTs != Number.MAX_VALUE) {
               spanEl.appendChild(
-                  tv.c.analysis.createTimeStamp(event.deletionTs));
+                  tr.b.units.createTimeStampSpan(event.deletionTs));
             }
             return spanEl;
           },
@@ -70,9 +71,9 @@
         {
           title: 'Second',
           value: function(event) {
-            var linkEl = document.createElement('tv-c-analysis-link');
+            var linkEl = document.createElement('tr-c-a-analysis-link');
             linkEl.setSelectionAndContent(function() {
-                return new tv.c.Selection(event);
+                return new tr.c.Selection(event);
             }, event.userFriendlyName);
             return linkEl;
           },
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view_test.html
index ebcacc3..fea9cee 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_object_sub_view_test.html
@@ -8,29 +8,28 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TraceModel = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var ObjectInstance = tv.c.trace_model.ObjectInstance;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var ObjectInstance = tr.model.ObjectInstance;
 
   test('instantiate_analysisWithObjects', function() {
-    var model = new TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var objects = p1.objects;
     var i10 = objects.idWasCreated(
-        '0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 10);
-    var s10 = objects.addSnapshot('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 10,
+        '0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 10);
+    var s10 = objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 10,
                                   'snapshot-1');
-    var s25 = objects.addSnapshot('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 25,
+    var s25 = objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 25,
                                   'snapshot-2');
-    var s40 = objects.addSnapshot('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 40,
+    var s40 = objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 40,
                                   'snapshot-3');
-    objects.idWasDeleted('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 45);
+    objects.idWasDeleted('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 45);
 
     var track = {};
     var selection = new Selection();
@@ -39,7 +38,7 @@
     selection.push(s25);
     selection.push(s40);
 
-    var analysisEl = document.createElement('tv-c-multi-object-sub-view');
+    var analysisEl = document.createElement('tr-c-a-multi-object-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view.html
index 2a7902a..067a3a8 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view.html
@@ -6,18 +6,18 @@
 -->
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/units/util.html">
 
-<polymer-element name="tv-c-multi-process-memory-dump-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-process-memory-dump-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
       display: flex;
     }
     </style>
-    <tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+    <tr-b-ui-table id="content"></tr-b-ui-table>
   </template>
 
   <script>
@@ -35,22 +35,22 @@
     set selection(selection) {
       this.currentSelection_ = selection;
 
-      selection = tv.b.asArray(selection).sort(
-          tv.b.Range.compareByMinTimes);
+      selection = tr.b.asArray(selection).sort(
+          tr.b.Range.compareByMinTimes);
 
       var table = this.$.content;
       table.tableColumns = [
         {
           title: 'Dump',
           value: function(row) {
-            var linkEl = document.createElement('tv-c-analysis-link');
+            var linkEl = document.createElement('tr-c-a-analysis-link');
             linkEl.setSelectionAndContent(function() {
-                return new tv.c.Selection(row);
+                return new tr.c.Selection(row);
             });
             var spanEl = document.createElement('span');
             spanEl.textContent = 'Process memory dump at ';
             linkEl.appendChild(spanEl);
-            linkEl.appendChild(tv.c.analysis.createTimeStamp(row.start));
+            linkEl.appendChild(tr.b.units.createTimeStampSpan(row.start));
             return linkEl;
           }
         }
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view_test.html
index 2f632e1..3204692 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_process_memory_dump_sub_view_test.html
@@ -8,19 +8,18 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TraceModel = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var GlobalMemoryDump = tv.c.trace_model.GlobalMemoryDump;
-  var ProcessMemoryDump = tv.c.trace_model.ProcessMemoryDump;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var GlobalMemoryDump = tr.model.GlobalMemoryDump;
+  var ProcessMemoryDump = tr.model.ProcessMemoryDump;
 
   test('basic', function() {
-    var m = new TraceModel();
+    var m = new tr.Model();
     var p = m.getOrCreateProcess(42);
 
     function addProcessMemoryDump(timestamp) {
@@ -41,7 +40,7 @@
     assert.equal(selection.length, 2);
 
     var subView = document.createElement(
-        'tv-c-multi-process-memory-dump-sub-view');
+        'tr-c-a-multi-process-memory-dump-sub-view');
     subView.selection = selection;
 
     this.addHTMLOutput(subView);
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view.html
index 265ea7b..92b53c2 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view.html
@@ -7,8 +7,8 @@
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 
-<polymer-element name="tv-c-multi-sample-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-sample-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -34,8 +34,8 @@
       this.$.content.textContent = '';
       this.currentSelection_ = selection;
 
-      if (tv.isDefined('tv.e.analysis.SamplingSummaryPanel')) {
-        var panel = new tv.e.analysis.SamplingSummaryPanel();
+      if (tr.isDefined('tr.e.analysis.SamplingSummaryPanel')) {
+        var panel = new tr.e.analysis.SamplingSummaryPanel();
         this.$.content.appendChild(panel);
         panel.selection = selection;
       } else {
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view_test.html
index 411864c..3293ae9 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_sample_sub_view_test.html
@@ -9,15 +9,15 @@
 <link rel="import" href="/core/analysis/multi_sample_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var newSampleNamed = tv.c.test_utils.newSampleNamed;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
+  var newSampleNamed = tr.c.test_utils.newSampleNamed;
 
   test('instantiate_withMultipleSamples', function() {
     var model = new Model();
@@ -41,7 +41,7 @@
     for (var i = 0; i < t53.samples.length; i++)
       selection.push(t53.samples[i]);
 
-    var view = document.createElement('tv-c-multi-sample-sub-view');
+    var view = document.createElement('tr-c-a-multi-sample-sub-view');
     view.style.height = '500px';
     this.addHTMLOutput(view);
     view.selection = selection;
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view.html
index fbe61e4..73022b1 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view.html
@@ -7,11 +7,10 @@
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
-<link rel="import" href="/core/analysis/flow_classifier.html">
-<link rel="import" href="/core/analysis/related_flows.html">
+<link rel="import" href="/core/analysis/related_events.html">
 
-<polymer-element name="tv-c-a-multi-thread-slice-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-thread-slice-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -21,7 +20,7 @@
       display: flex;
       flex: 1 1 auto;
     }
-    #content > tv-c-a-related-flows {
+    #content > tr-c-a-related-events {
       margin-left: 8px;
     }
     </style>
@@ -46,10 +45,10 @@
       // TODO(nduca): This is a gross hack for cc Frame Viewer, but its only
       // the frame viewer that needs this feature, so ~shrug~.
       if (window.RasterTaskView !== undefined) { // May not have been imported.
-        if (tv.e.cc.RasterTaskSelection.supports(selection)) {
-          var ltvSelection = new tv.e.cc.RasterTaskSelection(selection);
+        if (tr.e.cc.RasterTaskSelection.supports(selection)) {
+          var ltvSelection = new tr.e.cc.RasterTaskSelection(selection);
 
-          var ltv = new tv.e.cc.LayerTreeHostImplSnapshotView();
+          var ltv = new tr.e.cc.LayerTreeHostImplSnapshotView();
           ltv.objectSnapshot = ltvSelection.containingSnapshot;
           ltv.selection = ltvSelection;
           ltv.extraHighlightsByLayerId = ltvSelection.extraHighlightsByLayerId;
@@ -64,24 +63,15 @@
 
       this.$.content.textContent = '';
 
-      var mesv = document.createElement('tv-c-a-multi-event-sub-view');
+      var mesv = document.createElement('tr-c-a-multi-event-sub-view');
       mesv.selection = selection;
       this.$.content.appendChild(mesv);
 
-      var fc = new tv.c.analysis.FlowClassifier();
-      selection.forEach(function(slice) {
-        slice.inFlowEvents.forEach(function(flow) {
-          fc.addInFlow(flow);
-        });
-        slice.outFlowEvents.forEach(function(flow) {
-          fc.addOutFlow(flow);
-        });
-      });
-      if (fc.hasEvents) {
-        var rflows = document.createElement('tv-c-a-related-flows');
-        rflows.setFlows(
-            fc.inFlowEvents, fc.outFlowEvents, fc.internalFlowEvents);
-        this.$.content.appendChild(rflows);
+      var relatedEvents = document.createElement('tr-c-a-related-events');
+      relatedEvents.addRelatedEvents(selection);
+
+      if (relatedEvents.hasRelatedEvents()) {
+        this.$.content.appendChild(relatedEvents);
       }
     },
 
@@ -89,7 +79,7 @@
       if (this.$.content.children.length === 0)
         return false;
       var childTagName = this.$.content.children[0].tagName;
-      if (childTagName === 'TV-C-A-MULTI-EVENT-SUB-VIEW')
+      if (childTagName === 'TR-C-A-MULTI-EVENT-SUB-VIEW')
         return false;
 
       // Using raster task view.
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view_test.html
index 1e600a1..38df25d 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_thread_slice_sub_view_test.html
@@ -8,35 +8,38 @@
 <link rel="import" href="/core/analysis/multi_thread_slice_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/thread_slice.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newSliceEx = tv.c.test_utils.newSliceEx;
-  var newFlowEventEx = tv.c.test_utils.newFlowEventEx;
+tr.b.unittest.testSuite(function() {
+  var newSliceEx = tr.c.test_utils.newSliceEx;
+  var newFlowEventEx = tr.c.test_utils.newFlowEventEx;
 
   test('instantiate', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
     t53.sliceGroup.pushSlice(
-        newSliceEx({title: 'a', start: 0.0, duration: 0.5}));
+        newSliceEx({title: 'a', start: 0.0, duration: 0.5,
+                    type: tr.model.ThreadSlice}));
     t53.sliceGroup.pushSlice(
-        newSliceEx({title: 'b', start: 1.0, duration: 2}));
+        newSliceEx({title: 'b', start: 1.0, duration: 2,
+                    type: tr.model.ThreadSlice}));
     t53.sliceGroup.createSubSlices();
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(t53.sliceGroup.slices[0]);
     selection.push(t53.sliceGroup.slices[1]);
 
-    var viewEl = document.createElement('tv-c-a-multi-thread-slice-sub-view');
+    var viewEl = document.createElement('tr-c-a-multi-thread-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
 
   test('withFlows', function() {
-    var m = tv.c.test_utils.newModel(function(m) {
+    var m = tr.c.test_utils.newModel(function(m) {
       m.p1 = m.getOrCreateProcess(1);
 
       m.t2 = m.p1.getOrCreateThread(2);
@@ -44,11 +47,14 @@
       m.t4 = m.p1.getOrCreateThread(4);
 
       m.sA = m.t2.sliceGroup.pushSlice(
-          newSliceEx({title: 'a', start: 0, end: 5}));
+          newSliceEx({title: 'a', start: 0, end: 5,
+                      type: tr.model.ThreadSlice}));
       m.sB = m.t3.sliceGroup.pushSlice(
-          newSliceEx({title: 'b', start: 10, end: 15}));
+          newSliceEx({title: 'b', start: 10, end: 15,
+                      type: tr.model.ThreadSlice}));
       m.sC = m.t4.sliceGroup.pushSlice(
-          newSliceEx({title: 'c', start: 20, end: 20}));
+          newSliceEx({title: 'c', start: 20, end: 20,
+                      type: tr.model.ThreadSlice}));
 
       m.t2.createSubSlices();
       m.t3.createSubSlices();
@@ -66,12 +72,12 @@
       });
     });
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(m.sA);
     selection.push(m.sB);
     selection.push(m.sC);
 
-    var viewEl = document.createElement('tv-c-a-multi-thread-slice-sub-view');
+    var viewEl = document.createElement('tr-c-a-multi-thread-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view.html
index f27892f..ffbb3a6 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/multi_event_sub_view.html">
 
-<polymer-element name="tv-c-a-multi-thread-time-slice-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-multi-thread-time-slice-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -19,7 +19,7 @@
       flex: 1 1 auto;
     }
     </style>
-    <tv-c-a-multi-event-sub-view id="content"></tv-c-a-multi-event-sub-view>
+    <tr-c-a-multi-event-sub-view id="content"></tr-c-a-multi-event-sub-view>
   </template>
 
   <script>
diff --git a/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view_test.html
index 4c278ef..ab829a7 100644
--- a/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/multi_thread_time_slice_sub_view_test.html
@@ -8,13 +8,13 @@
 <link rel="import" href="/core/analysis/multi_thread_time_slice_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function createBasicModel() {
     var lines = [
       'Android.launcher-584   [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
@@ -26,7 +26,7 @@
       '       Binder_1-217   [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
     ];
 
-    return new tv.c.TraceModel(lines.join('\n'), false);
+    return new tr.Model(lines.join('\n'), false);
   }
 
   test('instantiate', function() {
@@ -34,12 +34,12 @@
 
     var thread = m.findAllThreadsNamed('Binder_1')[0];
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(thread.timeSlices[0]);
     selection.push(thread.timeSlices[1]);
 
     var viewEl = document.createElement(
-        'tv-c-a-multi-thread-time-slice-sub-view');
+        'tr-c-a-multi-thread-time-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/object_instance_view.html b/trace-viewer/trace_viewer/core/analysis/object_instance_view.html
index 6fda7aa..fbfce49 100644
--- a/trace-viewer/trace_viewer/core/analysis/object_instance_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/object_instance_view.html
@@ -11,8 +11,8 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.analysis', function() {
-  var ObjectInstanceView = tv.b.ui.define('object-instance-view');
+tr.exportTo('tr.c.analysis', function() {
+  var ObjectInstanceView = tr.b.ui.define('object-instance-view');
 
   ObjectInstanceView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -47,13 +47,13 @@
     }
   };
 
-  var options = new tv.b.ExtensionRegistryOptions(
-      tv.b.TYPE_BASED_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(
+      tr.b.TYPE_BASED_REGISTRY_MODE);
   options.mandatoryBaseClass = ObjectInstanceView;
   options.defaultMetadata = {
     showInTrackView: true
   };
-  tv.b.decorateExtensionRegistry(ObjectInstanceView, options);
+  tr.b.decorateExtensionRegistry(ObjectInstanceView, options);
 
   return {
     ObjectInstanceView: ObjectInstanceView
diff --git a/trace-viewer/trace_viewer/core/analysis/object_snapshot_view.html b/trace-viewer/trace_viewer/core/analysis/object_snapshot_view.html
index de5b0aa..2bbce1d 100644
--- a/trace-viewer/trace_viewer/core/analysis/object_snapshot_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/object_snapshot_view.html
@@ -11,8 +11,8 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.analysis', function() {
-  var ObjectSnapshotView = tv.b.ui.define('object-snapshot-view');
+tr.exportTo('tr.c.analysis', function() {
+  var ObjectSnapshotView = tr.b.ui.define('object-snapshot-view');
 
   ObjectSnapshotView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -47,14 +47,14 @@
     }
   };
 
-  var options = new tv.b.ExtensionRegistryOptions(
-      tv.b.TYPE_BASED_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(
+      tr.b.TYPE_BASED_REGISTRY_MODE);
   options.mandatoryBaseClass = ObjectSnapshotView;
   options.defaultMetadata = {
     showInstances: true,
     showInTrackView: true
   };
-  tv.b.decorateExtensionRegistry(ObjectSnapshotView, options);
+  tr.b.decorateExtensionRegistry(ObjectSnapshotView, options);
 
   return {
     ObjectSnapshotView: ObjectSnapshotView
diff --git a/trace-viewer/trace_viewer/core/analysis/related_events.html b/trace-viewer/trace_viewer/core/analysis/related_events.html
new file mode 100644
index 0000000..d30741a
--- /dev/null
+++ b/trace-viewer/trace_viewer/core/analysis/related_events.html
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/core/analysis/analysis_link.html">
+<link rel="import" href="/core/analysis/flow_classifier.html">
+<link rel="import" href="/core/selection.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/ui/dom_helpers.html">
+
+<polymer-element name="tr-c-a-related-events">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    #table {
+      flex: 1 1 auto;
+      align-self: stretch;
+    }
+    </style>
+    <tr-b-ui-table id="table"></tr-b-ui-table>
+  </template>
+
+  <script>
+  'use strict';
+
+  Polymer({
+    ready: function() {
+      this.eventGroups_ = [];
+
+      this.$.table.tableColumns = [
+        {
+          title: 'Event(s)',
+          value: function(row) { return row.type; },
+          width: '150px'
+        },
+        {
+          title: 'Link',
+          width: '100%',
+          value: function(row) {
+            var linkEl = document.createElement('tr-c-a-analysis-link');
+            if (row.name)
+              linkEl.setSelectionAndContent(row.selection, row.name);
+            else
+              linkEl.selection = row.selection;
+            return linkEl;
+          }
+        }
+      ];
+    },
+
+    hasRelatedEvents: function() {
+      return (this.eventGroups_ && this.eventGroups_.length > 0);
+    },
+
+    addRelatedEvents: function(selection) {
+      this.addConnectedFlows_(selection);
+      this.addConnectedEvents_(selection);
+      this.updateContents_();
+    },
+
+    addConnectedFlows_: function(selection) {
+      var classifier = new tr.c.analysis.FlowClassifier();
+      selection.forEach(function(slice) {
+        if (slice.inFlowEvents) {
+          slice.inFlowEvents.forEach(function(flow) {
+            classifier.addInFlow(flow);
+          });
+        }
+        if (slice.outFlowEvents) {
+          slice.outFlowEvents.forEach(function(flow) {
+            classifier.addOutFlow(flow);
+          });
+        }
+      });
+      if (!classifier.hasEvents())
+        return;
+
+      var addToEventGroups = function(type, flowEvent) {
+        this.eventGroups_.push({
+          type: type,
+          selection: new tr.c.Selection(flowEvent),
+          name: flowEvent.title
+        });
+      };
+
+      classifier.inFlowEvents.forEach(
+          addToEventGroups.bind(this, 'Incoming flow'));
+      classifier.outFlowEvents.forEach(
+          addToEventGroups.bind(this, 'Outgoing flow'));
+      classifier.internalFlowEvents.forEach(
+          addToEventGroups.bind(this, 'Internal flow'));
+    },
+
+    addConnectedEvents_: function(selection) {
+      // Preceding and following events are only well-defined for single
+      // selections.
+      if (selection.length === 1)
+        this.addConnectedEventsForSlice_(selection[0]);
+      else
+        this.addConnectedEventsForSelection_(selection);
+    },
+
+    addConnectedEventsForSlice_: function(slice) {
+      var precedingEventsSelection = undefined;
+      var followingEventsSelection = undefined;
+      if (slice.inFlowEvents && slice.inFlowEvents.length !== 0) {
+        precedingEventsSelection = new tr.c.Selection();
+        this.recursivelyAddConnectedEvents_(precedingEventsSelection, {}, slice,
+            function(event) { return event.inFlowEvents; });
+        this.eventGroups_.push({
+          type: 'Preceding events',
+          selection: precedingEventsSelection
+        });
+      }
+      if (slice.outFlowEvents && slice.outFlowEvents.length !== 0) {
+        followingEventsSelection = new tr.c.Selection();
+        this.recursivelyAddConnectedEvents_(followingEventsSelection, {}, slice,
+            function(event) { return event.outFlowEvents; });
+        this.eventGroups_.push({
+          type: 'Following events',
+          selection: followingEventsSelection
+        });
+      }
+      if (precedingEventsSelection && followingEventsSelection) {
+        var allEventsSelection = new tr.c.Selection();
+        for (var i = 0; i < precedingEventsSelection.length; ++i)
+          allEventsSelection.push(precedingEventsSelection[i]);
+        // Do not add the first event of followingEventsSelection since it's
+        // the slice too.
+        for (var i = 1; i < followingEventsSelection.length; ++i)
+          allEventsSelection.push(followingEventsSelection[i]);
+        this.eventGroups_.push({
+          type: 'All connected events',
+          selection: allEventsSelection
+        });
+      }
+    },
+
+    addConnectedEventsForSelection_: function(selection) {
+      var eventIds = {};
+      var allEventsSelection = new tr.c.Selection();
+      selection.forEach(function(slice) {
+        this.recursivelyAddConnectedEvents_(allEventsSelection, eventIds, slice,
+            function(event) {
+              var flows = [];
+              if (event.inFlowEvents)
+                flows = flows.concat(event.inFlowEvents);
+              if (event.outFlowEvents)
+                flows = flows.concat(event.outFlowEvents);
+              return flows;
+            });
+      }.bind(this));
+      // Add related events if it contains more than the original selection.
+      if (allEventsSelection.length > selection.length) {
+        this.eventGroups_.push({
+          type: 'All connected events',
+          selection: allEventsSelection
+        });
+      }
+    },
+
+    updateContents_: function() {
+      var table = this.$.table;
+      if (this.eventGroups_ === undefined)
+        table.tableRows = [];
+      else
+        table.tableRows = this.eventGroups_.slice();
+      table.rebuild();
+    },
+
+    recursivelyAddConnectedEvents_: function(selection, eventIds, event,
+                                             getFlows) {
+      if (!event || eventIds[event.guid])
+        return;
+      eventIds[event.guid] = true;
+      selection.push(event);
+      var flowEvents = getFlows(event);
+      if (!flowEvents)
+        return;
+      for (var i = 0; i < flowEvents.length; ++i) {
+        selection.push(flowEvents[i]);
+        this.recursivelyAddConnectedEvents_(selection, eventIds,
+            flowEvents[i].startSlice, getFlows);
+        this.recursivelyAddConnectedEvents_(selection, eventIds,
+            flowEvents[i].endSlice, getFlows);
+      }
+    }
+  });
+  </script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/related_events_test.html b/trace-viewer/trace_viewer/core/analysis/related_events_test.html
new file mode 100644
index 0000000..330e6f0
--- /dev/null
+++ b/trace-viewer/trace_viewer/core/analysis/related_events_test.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/core/analysis/related_events.html">
+<link rel="import" href="/core/test_utils.html">
+<link rel="import" href="/core/selection.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/thread_slice.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  var newSliceEx = tr.c.test_utils.newSliceEx;
+  var newFlowEventEx = tr.c.test_utils.newFlowEventEx;
+
+  test('instantiate', function() {
+    var m = tr.c.test_utils.newModel(function(m) {
+      m.p1 = m.getOrCreateProcess(1);
+
+      m.t2 = m.p1.getOrCreateThread(2);
+      m.t3 = m.p1.getOrCreateThread(3);
+      m.t4 = m.p1.getOrCreateThread(4);
+
+      m.sA = m.t2.sliceGroup.pushSlice(
+          newSliceEx({title: 'a', start: 0, end: 5,
+                      type: tr.model.ThreadSlice}));
+      m.sB = m.t3.sliceGroup.pushSlice(
+          newSliceEx({title: 'b', start: 10, end: 15,
+                      type: tr.model.ThreadSlice}));
+      m.sC = m.t4.sliceGroup.pushSlice(
+          newSliceEx({title: 'c', start: 20, end: 20,
+                      type: tr.model.ThreadSlice}));
+
+      m.t2.createSubSlices();
+      m.t3.createSubSlices();
+      m.t4.createSubSlices();
+
+      m.f1 = newFlowEventEx({
+        'title': 'flowish', start: 0, end: 10,
+        startSlice: m.sA,
+        endSlice: m.sB
+      });
+      m.f2 = newFlowEventEx({
+        'title': 'flowish', start: 15, end: 21,
+        startSlice: m.sB,
+        endSlice: m.sC
+      });
+    });
+
+    var viewEl = document.createElement('tr-c-a-related-events');
+    viewEl.addRelatedEvents(new tr.c.Selection([m.sA, m.f1, m.sB, m.f2, m.sC]));
+    this.addHTMLOutput(viewEl);
+  });
+
+});
+</script>
diff --git a/trace-viewer/trace_viewer/core/analysis/related_flows.html b/trace-viewer/trace_viewer/core/analysis/related_flows.html
deleted file mode 100644
index 646149d..0000000
--- a/trace-viewer/trace_viewer/core/analysis/related_flows.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2015 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="import" href="/core/analysis/analysis_link.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/base/ui/dom_helpers.html">
-
-<polymer-element name="tv-c-a-related-flows">
-  <template>
-    <style>
-    :host {
-      display: flex;
-      flex-direction: column;
-    }
-    #table {
-      flex: 1 1 auto;
-      align-self: stretch;
-    }
-    </style>
-    <tracing-analysis-nested-table id="table"></tracing-analysis-nested-table>
-  </template>
-
-  <script>
-  'use strict';
-
-  Polymer({
-    ready: function() {
-      this.inSelection_ = undefined;
-      this.outSelection_ = undefined;
-      this.internalSelection_ = undefined;
-
-      this.$.table.tableColumns = [
-        {
-          title: 'Direction',
-          value: function(row) { return row.direction; },
-          width: '150px'
-        },
-        {
-          title: 'Title',
-          width: '100%',
-          value: function(row) {
-            var linkEl = document.createElement('tv-c-analysis-link');
-            linkEl.setSelectionAndContent(function() {
-                return new tv.c.Selection(row.event);
-            });
-            linkEl.appendChild(tv.b.ui.createSpan({
-              textContent: row.event.title
-            }));
-            return linkEl;
-          }
-        }
-      ];
-    },
-
-    clearFlows: function() {
-      this.inSelection_ = undefined;
-      this.outSelection_ = undefined;
-      this.internalSelection_ = undefined;
-      this.updateContents_();
-    },
-
-    setFlows: function(inSelection, outSelection, opt_internalSelection) {
-      this.inSelection_ = inSelection;
-      this.outSelection_ = outSelection;
-      if (opt_internalSelection)
-        this.internalSelection_ = opt_internalSelection;
-      else
-        this.internalSelection_ = new tv.c.Selection();
-      this.updateContents_();
-    },
-
-    updateContents_: function() {
-      var table = this.$.table;
-      if (this.inSelection_ === undefined || this.outSelection_ === undefined) {
-        table.tableRows = [];
-        table.rebuild();
-        return;
-      }
-
-      var rows = [];
-      this.inSelection_.forEach(function(fe) {
-        rows.push({
-          direction: 'Incoming',
-          event: fe
-        });
-      });
-      this.outSelection_.forEach(function(fe) {
-        rows.push({
-          direction: 'Outgoing',
-          event: fe
-        });
-      });
-      this.internalSelection_.forEach(function(fe) {
-        rows.push({
-          direction: 'Internal',
-          event: fe
-        });
-      });
-
-      table.tableRows = rows;
-      table.rebuild();
-    }
-  });
-  </script>
-</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/related_flows_test.html b/trace-viewer/trace_viewer/core/analysis/related_flows_test.html
deleted file mode 100644
index 49242db..0000000
--- a/trace-viewer/trace_viewer/core/analysis/related_flows_test.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2015 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="import" href="/core/analysis/related_flows.html">
-<link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() {
-  var newSliceEx = tv.c.test_utils.newSliceEx;
-  var newFlowEventEx = tv.c.test_utils.newFlowEventEx;
-
-  test('instantiate', function() {
-    var m = tv.c.test_utils.newModel(function(m) {
-      m.p1 = m.getOrCreateProcess(1);
-
-      m.t2 = m.p1.getOrCreateThread(2);
-      m.t3 = m.p1.getOrCreateThread(3);
-      m.t4 = m.p1.getOrCreateThread(4);
-
-      m.sA = m.t2.sliceGroup.pushSlice(
-          newSliceEx({title: 'a', start: 0, end: 5}));
-      m.sB = m.t3.sliceGroup.pushSlice(
-          newSliceEx({title: 'b', start: 10, end: 15}));
-      m.sC = m.t4.sliceGroup.pushSlice(
-          newSliceEx({title: 'c', start: 20, end: 20}));
-
-      m.t2.createSubSlices();
-      m.t3.createSubSlices();
-      m.t4.createSubSlices();
-
-      m.f1 = newFlowEventEx({
-        'title': 'flowish', start: 0, end: 10,
-        startSlice: m.sA,
-        endSlice: m.sB
-      });
-      m.f2 = newFlowEventEx({
-        'title': 'flowish', start: 15, end: 21,
-        startSlice: m.sB,
-        endSlice: m.sC
-      });
-    });
-
-    var inSel = new tv.c.Selection([m.f1]);
-    var outSel = new tv.c.Selection([m.f2]);
-
-    var viewEl = document.createElement('tv-c-a-related-flows');
-    viewEl.setFlows(inSel, outSel);
-    this.addHTMLOutput(viewEl);
-  });
-
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/analysis/selection_summary_table.html b/trace-viewer/trace_viewer/core/analysis/selection_summary_table.html
index e860cdf..e76ba8b 100644
--- a/trace-viewer/trace_viewer/core/analysis/selection_summary_table.html
+++ b/trace-viewer/trace_viewer/core/analysis/selection_summary_table.html
@@ -6,11 +6,11 @@
 -->
 
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/analysis/time_span.html">
-<link rel="import" href="/core/analysis/time_stamp.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/units/time_duration_span.html">
+<link rel="import" href="/base/units/time_stamp_span.html">
 
-<polymer-element name='tv-c-a-selection-summary-table'>
+<polymer-element name='tr-c-a-selection-summary-table'>
   <template>
     <style>
     :host {
@@ -21,8 +21,8 @@
       align-self: stretch;
     }
     </style>
-    <tracing-analysis-nested-table id="table">
-    </tracing-analysis-nested-table>
+    <tr-b-ui-table id="table">
+    </tr-b-ui-table>
     </div>
   </template>
   <script>
@@ -30,7 +30,7 @@
 
   Polymer({
     created: function() {
-      this.selection_ = new tv.b.Range();
+      this.selection_ = new tr.b.Range();
     },
 
     ready: function() {
@@ -72,12 +72,12 @@
       rows.push({
         title: 'Selection start',
         value: hasRange ?
-            tv.c.analysis.createTimeStamp(selection.bounds.min) : '<empty>'
+            tr.b.units.createTimeStampSpan(selection.bounds.min) : '<empty>'
       });
       rows.push({
         title: 'Selection extent',
         value: hasRange ?
-            tv.c.analysis.createTimeSpan(selection.bounds.range) : '<empty>'
+            tr.b.units.createTimeSpan(selection.bounds.range) : '<empty>'
       });
 
       this.$.table.tableRows = rows;
diff --git a/trace-viewer/trace_viewer/core/analysis/selection_summary_table_test.html b/trace-viewer/trace_viewer/core/analysis/selection_summary_table_test.html
index 89c81e5..a4a1db9 100644
--- a/trace-viewer/trace_viewer/core/analysis/selection_summary_table_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/selection_summary_table_test.html
@@ -9,35 +9,35 @@
 <link rel="import" href="/core/analysis/selection_summary_table.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
   test('noSelection', function() {
-    var summaryTable = document.createElement('tv-c-a-selection-summary-table');
+    var summaryTable = document.createElement('tr-c-a-selection-summary-table');
     summaryTable.selection = undefined;
     this.addHTMLOutput(summaryTable);
 
-    var tableEl = tv.b.findDeepElementMatching(
-        summaryTable, 'tracing-analysis-nested-table');
+    var tableEl = tr.b.findDeepElementMatching(
+        summaryTable, 'tr-b-ui-table');
     assert.equal(tableEl.tableRows[0].value, '<empty>');
     assert.equal(tableEl.tableRows[1].value, '<empty>');
   });
 
   test('emptySelection', function() {
-    var summaryTable = document.createElement('tv-c-a-selection-summary-table');
+    var summaryTable = document.createElement('tr-c-a-selection-summary-table');
     var selection = new Selection();
     summaryTable.selection = selection;
     this.addHTMLOutput(summaryTable);
 
-    var tableEl = tv.b.findDeepElementMatching(
-        summaryTable, 'tracing-analysis-nested-table');
+    var tableEl = tr.b.findDeepElementMatching(
+        summaryTable, 'tr-b-ui-table');
     assert.equal(tableEl.tableRows[0].value, '<empty>');
     assert.equal(tableEl.tableRows[1].value, '<empty>');
   });
@@ -54,12 +54,12 @@
     selection.push(tsg.slices[0]);
     selection.push(tsg.slices[1]);
 
-    var summaryTable = document.createElement('tv-c-a-selection-summary-table');
+    var summaryTable = document.createElement('tr-c-a-selection-summary-table');
     summaryTable.selection = selection;
     this.addHTMLOutput(summaryTable);
 
-    var tableEl = tv.b.findDeepElementMatching(
-        summaryTable, 'tracing-analysis-nested-table');
+    var tableEl = tr.b.findDeepElementMatching(
+        summaryTable, 'tr-b-ui-table');
     assert.equal(tableEl.tableRows[0].value.timestamp, 0);
     assert.equal(tableEl.tableRows[1].value.duration, 3);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_alert_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_alert_sub_view.html
index fc90abd..627b0c9 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_alert_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_alert_sub_view.html
@@ -9,8 +9,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
 
-<polymer-element name="tv-c-single-alert-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-alert-sub-view"
+    extends="tr-c-a-sub-view">
   <script>
   'use strict';
 
@@ -23,12 +23,12 @@
       this.currentSelection_ = selection;
 
       this.textContent = '';
-      var realView = document.createElement('tv-c-a-single-event-sub-view');
+      var realView = document.createElement('tr-c-a-single-event-sub-view');
       realView.addExtraRowsCallback = function(rows) {
         // Alert description.
         var alert = this.currentSelection_[0];
 
-        var descriptionEl = tv.b.ui.createSpan({
+        var descriptionEl = tr.b.ui.createSpan({
           textContent: alert.info.description
         });
         rows.push({
@@ -40,9 +40,9 @@
         if (alert.associatedEvents.length) {
           var eventSubRows = [];
           alert.associatedEvents.forEach(function(event, i) {
-            var linkEl = document.createElement('tv-c-analysis-link');
+            var linkEl = document.createElement('tr-c-a-analysis-link');
             linkEl.setSelectionAndContent(function() {
-              return new tv.c.Selection(event);
+              return new tr.c.Selection(event);
             }, event.userFriendlyName);
             eventSubRows.push({
               name: i,
diff --git a/trace-viewer/trace_viewer/core/analysis/single_async_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_async_slice_sub_view.html
index b4ad4d5..3c586be 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_async_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_async_slice_sub_view.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
 
-<polymer-element name="tv-c-a-single-async-slice-sub-view"
-    extends="tv-c-a-single-event-sub-view">
+<polymer-element name="tr-c-a-single-async-slice-sub-view"
+    extends="tr-c-a-single-event-sub-view">
   <script>
   'use strict';
 
@@ -31,7 +31,7 @@
         return undefined;
       if (!this.currentSelection_[0].associatedEvents)
         return;
-      return new tv.c.Selection(this.currentSelection_[0].associatedEvents);
+      return new tr.c.Selection(this.currentSelection_[0].associatedEvents);
     }
   });
   </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view.html
index 48a2f3b..99e7333 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view.html
@@ -6,11 +6,11 @@
 -->
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/core/analysis/analysis_link.html">
 <link rel="import" href="/base/utils.html">
-<polymer-element name="tv-c-single-cpu-slice-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-cpu-slice-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     table {
@@ -61,8 +61,8 @@
       <tr>
         <td>Args:</td>
         <td>
-          <tv-c-analysis-generic-object-view id="args">
-          </tv-c-analysis-generic-object-view>
+          <tr-c-a-generic-object-view id="args">
+          </tr-c-a-generic-object-view>
         </td>
       </tr>
     </table>
@@ -82,7 +82,7 @@
     set selection(selection) {
       if (selection.length !== 1)
         throw new Error('Only supports single slices');
-      if (!(selection[0] instanceof tv.c.trace_model.CpuSlice))
+      if (!(selection[0] instanceof tr.model.CpuSlice))
         throw new Error('Only supports thread time slices');
 
       this.currentSelection_ = selection;
@@ -103,18 +103,18 @@
       }
 
       shadowRoot.querySelector('#start').textContent =
-          tv.c.analysis.tsString(cpuSlice.start);
+          tr.b.units.tsString(cpuSlice.start);
 
       shadowRoot.querySelector('#duration').textContent =
-          tv.c.analysis.tsString(cpuSlice.duration);
+          tr.b.units.tsString(cpuSlice.duration);
       var runningThreadEl = shadowRoot.querySelector('#running-thread');
 
       var timeSlice = cpuSlice.getAssociatedTimeslice();
       if (!timeSlice) {
         runningThreadEl.parentElement.style.display = 'none';
       } else {
-        var threadLink = document.createElement('tv-c-analysis-link');
-        threadLink.selection = new tv.c.Selection(timeSlice);
+        var threadLink = document.createElement('tr-c-a-analysis-link');
+        threadLink.selection = new tr.c.Selection(timeSlice);
         threadLink.textContent = 'Click to select';
         runningThreadEl.parentElement.style.display = '';
         runningThreadEl.textContent = '';
diff --git a/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view_test.html
index 8f84cc5..275bad6 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_cpu_slice_sub_view_test.html
@@ -5,14 +5,14 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/analysis/single_cpu_slice_sub_view.html">
 <link rel="import" href="/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function createBasicModel() {
     var lines = [
       'Android.launcher-584   [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
@@ -24,7 +24,7 @@
       '       Binder_1-217   [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
     ];
 
-    return new tv.c.TraceModel(lines.join('\n'), false);
+    return new tr.Model(lines.join('\n'), false);
   }
 
   test('cpuSliceView_withCpuSliceOnExistingThread', function() {
@@ -39,8 +39,8 @@
     assert.isDefined(thread);
     assert.equal(cpuSlice.threadThatWasRunning, thread);
 
-    var view = document.createElement('tv-c-single-cpu-slice-sub-view');
-    var selection = new tv.c.Selection();
+    var view = document.createElement('tr-c-a-single-cpu-slice-sub-view');
+    var selection = new tr.c.Selection();
     selection.push(cpuSlice);
     view.selection = selection;
     this.addHTMLOutput(view);
@@ -52,7 +52,7 @@
       assert.equal(thread.timeSlices[0], e.selection[0]);
       didSelectionChangeHappen = true;
     });
-    view.shadowRoot.querySelector('tv-c-analysis-link').click();
+    view.shadowRoot.querySelector('tr-c-a-analysis-link').click();
     assert.isTrue(didSelectionChangeHappen);
   });
 
@@ -65,10 +65,10 @@
     assert.equal('Android.launcher', cpuSlice.title);
     assert.isUndefined(cpuSlice.thread);
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(cpuSlice);
 
-    var view = document.createElement('tv-c-single-cpu-slice-sub-view');
+    var view = document.createElement('tr-c-a-single-cpu-slice-sub-view');
     view.selection = selection;
     this.addHTMLOutput(view);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_event_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_event_sub_view.html
index 6f599ec..32bb6a9 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_event_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_event_sub_view.html
@@ -6,17 +6,17 @@
 -->
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/time_span.html">
-<link rel="import" href="/core/analysis/time_stamp.html">
+<link rel="import" href="/base/units/time_duration_span.html">
+<link rel="import" href="/base/units/time_stamp_span.html">
 <link rel="import" href="/core/analysis/stack_frame.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
-<link rel="import" href="/core/analysis/table_builder.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/base/base.html">
 <link rel="import" href="/base/ui.html">
 
-<polymer-element name="tv-c-a-single-event-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-event-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -28,8 +28,8 @@
       align-self: stretch;
     }
     </style>
-    <tracing-analysis-nested-table id="table">
-    </tracing-analysis-nested-table>
+    <tr-b-ui-table id="table">
+    </tr-b-ui-table>
   </template>
   <script>
   'use strict';
@@ -79,31 +79,34 @@
       if (event.category)
         rows.push({ name: 'Category', value: event.category });
 
-      var startEl = document.createElement('tv-c-a-time-stamp');
+      var startEl = document.createElement('tr-b-u-time-stamp-span');
       startEl.timestamp = event.start;
       rows.push({ name: 'Start', value: startEl });
 
       if (event.duration) {
-        var wallDurationEl = document.createElement('tv-c-a-time-span');
+        var wallDurationEl = document.createElement(
+            'tr-b-u-time-duration-span');
         wallDurationEl.duration = event.duration;
         rows.push({ name: 'Wall Duration', value: wallDurationEl });
       }
 
       if (event.cpuDuration) {
-        var cpuDurationEl = document.createElement('tv-c-a-time-span');
+        var cpuDurationEl = document.createElement(
+            'tr-b-u-time-duration-span');
         cpuDurationEl.duration = event.cpuDuration;
         rows.push({ name: 'CPU Duration', value: cpuDurationEl });
       }
 
       if (event.subSlices !== undefined && event.subSlices.length !== 0) {
         if (event.selfTime) {
-          var selfTimeEl = document.createElement('tv-c-a-time-span');
+          var selfTimeEl = document.createElement('tr-b-u-time-duration-span');
           selfTimeEl.duration = event.selfTime;
           rows.push({ name: 'Self Time', value: selfTimeEl });
         }
 
         if (event.cpuSelfTime) {
-          var cpuSelfTimeEl = document.createElement('tv-c-a-time-span');
+          var cpuSelfTimeEl = document.createElement(
+              'tr-b-u-time-duration-span');
           cpuSelfTimeEl.duration = event.cpuSelfTime;
           if (event.cpuSelfTime > event.selfTime) {
             cpuSelfTimeEl.warning =
@@ -118,13 +121,14 @@
       }
 
       if (event.durationInUserTime) {
-        var durationInUserTimeEl = document.createElement('tv-c-a-time-span');
+        var durationInUserTimeEl = document.createElement(
+            'tr-b-u-time-duration-span');
         durationInUserTimeEl.duration = event.durationInUserTime;
         rows.push({ name: 'Duration (U)', value: durationInUserTimeEl });
       }
 
       function createStackFrameEl(sf) {
-        var sfEl = document.createElement('tv-c-a-stack-frame');
+        var sfEl = document.createElement('tr-c-a-stack-frame');
         sfEl.stackFrame = sf;
         return sfEl;
       }
@@ -149,7 +153,7 @@
       }
 
       if (event.info) {
-        var descriptionEl = tv.b.ui.createDiv({
+        var descriptionEl = tr.b.ui.createDiv({
             textContent: event.info.description,
             maxWidth: '300px'
         });
@@ -176,9 +180,9 @@
       if (event.associatedAlerts.length) {
         var alertSubRows = [];
         event.associatedAlerts.forEach(function(alert) {
-          var linkEl = document.createElement('tv-c-analysis-link');
+          var linkEl = document.createElement('tr-c-a-analysis-link');
           linkEl.setSelectionAndContent(function() {
-            return new tv.c.Selection(alert);
+            return new tr.c.Selection(alert);
           }, alert.info.description);
           alertSubRows.push({
             name: alert.title,
@@ -203,7 +207,7 @@
         var subRows = [];
         for (var argName in args) {
           var argView =
-              document.createElement('tv-c-analysis-generic-object-view');
+              document.createElement('tr-c-a-generic-object-view');
           argView.object = args[argName];
           subRows.push({ name: argName,
                       value: argView});
diff --git a/trace-viewer/trace_viewer/core/analysis/single_event_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_event_sub_view_test.html
index 76240f5..d1bb382 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_event_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_event_sub_view_test.html
@@ -9,21 +9,21 @@
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Thread = tv.c.trace_model.Thread;
-  var Selection = tv.c.Selection;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-  var newSliceCategory = tv.c.test_utils.newSliceCategory;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Thread = tr.model.Thread;
+  var Selection = tr.c.Selection;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+  var newSliceCategory = tr.c.test_utils.newSliceCategory;
 
   function createSelection(customizeThreadCallback) {
     var model = new Model();
-    var importOptions = new tv.c.ImportOptions();
+    var importOptions = new tr.ImportOptions();
     importOptions.customizeModelCallback = function() {
       var t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
       customizeThreadCallback(t53, model);
@@ -46,8 +46,8 @@
     var options = opt_options || {};
     return createSelection(function(t53, model) {
       if (options.withStartStackFrame || options.withEndStackFrame) {
-        var fA = tv.c.test_utils.newStackTrace(model, 'cat', ['a1', 'a2']);
-        var fB = tv.c.test_utils.newStackTrace(model, 'cat', ['b1', 'b2']);
+        var fA = tr.c.test_utils.newStackTrace(model, 'cat', ['a1', 'a2']);
+        var fB = tr.c.test_utils.newStackTrace(model, 'cat', ['b1', 'b2']);
       }
 
       var slice;
@@ -69,7 +69,7 @@
   test('instantiate_withSingleSlice', function() {
     var selection = createSelectionWithSingleSlice();
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
   });
@@ -77,15 +77,15 @@
   test('alerts', function() {
     var slice = newSliceNamed('b', 0, 0.002);
 
-    var ALERT_INFO_1 = new tv.c.trace_model.EventInfo(
+    var ALERT_INFO_1 = new tr.model.EventInfo(
         'Alert 1', 'Critical alert');
 
-    var alert = new tv.c.trace_model.Alert(ALERT_INFO_1, 5, [slice]);
+    var alert = new tr.model.Alert(ALERT_INFO_1, 5, [slice]);
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(slice);
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
   });
@@ -102,12 +102,12 @@
       t53.sliceGroup.pushSlice(slice);
     });
 
-    var subView = document.createElement('tv-c-a-single-event-sub-view');
+    var subView = document.createElement('tr-c-a-single-event-sub-view');
     subView.selection = selection;
     this.addHTMLOutput(subView);
 
-    var gov = tv.b.findDeepElementMatching(subView,
-                                           'tv-c-analysis-generic-object-view');
+    var gov = tr.b.findDeepElementMatching(subView,
+                                           'tr-c-a-generic-object-view');
     assert.isDefined(gov);
   });
 
@@ -115,7 +115,7 @@
   test('instantiate_withSingleSliceCategory', function() {
     var selection = createSelectionWithSingleSlice({withCategory: true});
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
   });
@@ -124,11 +124,11 @@
     var selection = createSelectionWithSingleSlice(
         {withStartStackFrame: 'a'});
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
 
-    var e = tv.b.findDeepElementWithTextContent(
+    var e = tr.b.findDeepElementWithTextContent(
         analysisEl, /Start Stack Trace/);
     assert.isDefined(e);
     assert.isDefined(e.nextSibling.children[0].stackFrame);
@@ -138,11 +138,11 @@
     var selection = createSelectionWithSingleSlice(
         {withEndStackFrame: 'b'});
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
 
-    var e = tv.b.findDeepElementWithTextContent(
+    var e = tr.b.findDeepElementWithTextContent(
         analysisEl, /End Stack Trace/);
     assert.isDefined(e);
     assert.isDefined(e.nextSibling.children[0].stackFrame);
@@ -154,17 +154,17 @@
         {withStartStackFrame: 'a',
          withEndStackFrame: 'b'});
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
 
-    var eA = tv.b.findDeepElementWithTextContent(
+    var eA = tr.b.findDeepElementWithTextContent(
         analysisEl, /Start Stack Trace/);
     assert.isDefined(eA);
     assert.isDefined(eA.nextSibling.children[0].stackFrame);
     assert.equal(eA.nextSibling.children[0].stackFrame.title, 'a2');
 
-    var eB = tv.b.findDeepElementWithTextContent(
+    var eB = tr.b.findDeepElementWithTextContent(
         analysisEl, /End Stack Trace/);
     assert.isDefined(eB);
     assert.isDefined(eB.nextSibling.children[0].stackFrame);
@@ -176,11 +176,11 @@
         {withStartStackFrame: 'a',
          withEndStackFrame: 'a'});
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
 
-    var e = tv.b.findDeepElementWithTextContent(
+    var e = tr.b.findDeepElementWithTextContent(
         analysisEl, /Start\+End Stack Trace/);
     assert.isDefined(e);
     assert.isDefined(e.nextSibling.children[0].stackFrame);
@@ -189,11 +189,11 @@
 
   test('analyzeSelectionWithSingleSlice', function() {
     var selection = createSelectionWithSingleSlice();
-    var subView = document.createElement('tv-c-a-single-event-sub-view');
+    var subView = document.createElement('tr-c-a-single-event-sub-view');
     subView.selection = selection;
 
-    var table = tv.b.findDeepElementMatching(
-        subView, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        subView, 'tr-b-ui-table');
     assert.equal(table.tableRows.length, 3);
     assert.equal(table.tableRows[0].value, 'b');
     assert.equal(table.tableRows[1].value.timestamp, 0);
@@ -203,11 +203,11 @@
   test('analyzeSelectionWithSingleSliceCategory', function() {
     var selection = createSelectionWithSingleSlice({withCategory: true});
 
-    var subView = document.createElement('tv-c-a-single-event-sub-view');
+    var subView = document.createElement('tr-c-a-single-event-sub-view');
     subView.selection = selection;
 
-    var table = tv.b.findDeepElementMatching(
-        subView, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        subView, 'tr-b-ui-table');
     assert.equal(table.tableRows.length, 4);
     assert.equal(table.tableRows[0].value, 'b');
     assert.equal(table.tableRows[1].value, 'foo');
@@ -232,24 +232,24 @@
     selection.push(t1.sliceGroup.slices[0]);
     assert.equal(selection.length, 1);
 
-    var subView = document.createElement('tv-c-a-single-event-sub-view');
+    var subView = document.createElement('tr-c-a-single-event-sub-view');
     subView.selection = selection;
     this.addHTMLOutput(subView);
 
-    var analysisLink = tv.b.findDeepElementMatching(subView,
-                                                    'tv-c-analysis-link');
+    var analysisLink = tr.b.findDeepElementMatching(subView,
+                                                    'tr-c-a-analysis-link');
     assert.isDefined(analysisLink);
   });
 
   test('instantiate_withSingleSliceContainingInfo', function() {
     var slice = newSliceNamed('b', 0, 1);
-    slice.info = new tv.c.trace_model.EventInfo(
+    slice.info = new tr.model.EventInfo(
         'Info title', 'Description');
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(slice);
 
-    var analysisEl = document.createElement('tv-c-a-single-event-sub-view');
+    var analysisEl = document.createElement('tr-c-a-single-event-sub-view');
     analysisEl.selection = selection;
     this.addHTMLOutput(analysisEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view.html
index fa6ee37..73cbf67 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view.html
@@ -9,8 +9,8 @@
 <link rel="import" href="/core/analysis/analysis_link.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
 
-<polymer-element name="tv-c-single-flow-event-sub-view"
-    extends="tv-c-a-single-event-sub-view">
+<polymer-element name="tr-c-a-single-flow-event-sub-view"
+    extends="tr-c-a-single-event-sub-view">
   <script>
   'use strict';
 
@@ -26,9 +26,9 @@
       });
 
       function createLinkTo(slice) {
-        var linkEl = document.createElement('tv-c-analysis-link');
+        var linkEl = document.createElement('tr-c-a-analysis-link');
         linkEl.setSelectionAndContent(function() {
-            return new tv.c.Selection(slice);
+            return new tr.c.Selection(slice);
         });
         linkEl.textContent = slice.userFriendlyName;
         return linkEl;
diff --git a/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view_test.html
index a79c439..df3179a 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_flow_event_sub_view_test.html
@@ -8,15 +8,15 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var test_utils = tv.c.test_utils;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
+  var test_utils = tr.c.test_utils;
 
   test('analyzeSelectionWithSingleEvent', function() {
     var model = test_utils.newModel(function(model) {
@@ -44,7 +44,7 @@
     selection.push(model.fe);
     assert.equal(selection.length, 1);
 
-    var subView = document.createElement('tv-c-single-flow-event-sub-view');
+    var subView = document.createElement('tr-c-a-single-flow-event-sub-view');
     subView.selection = selection;
     this.addHTMLOutput(subView);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_frame_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_frame_sub_view.html
index 2026d19..5d2f8c7 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_frame_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_frame_sub_view.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/alert_sub_view.html">
 
-<polymer-element name="tv-c-single-frame-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-frame-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -21,8 +21,8 @@
       align-self: stretch;
     }
     </style>
-    <tv-c-a-alert-sub-view id="asv">
-    </tv-c-a-alert-sub-view>
+    <tr-c-a-alert-sub-view id="asv">
+    </tr-c-a-alert-sub-view>
   </template>
   <script>
   'use strict';
@@ -40,13 +40,13 @@
       if (selection.length != 1)
         throw new Error('Only supports single frame!');
       this.currentSelection_ = selection;
-      this.$.asv.selection = new tv.c.Selection(selection[0].associatedAlerts);
+      this.$.asv.selection = new tr.c.Selection(selection[0].associatedAlerts);
     },
 
     get relatedEventsToHighlight() {
       if (!this.currentSelection_)
         return undefined;
-      return new tv.c.Selection(this.currentSelection_[0].associatedEvents);
+      return new tr.c.Selection(this.currentSelection_[0].associatedEvents);
     }
   });
   </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view.html
index 2c29466..c113a94 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view.html
@@ -8,11 +8,11 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/memory_dump_view.html">
 
-<polymer-element name="tv-c-single-global-memory-dump-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-global-memory-dump-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
-    <tv-c-memory-dump-view id="memory_dump_view">
-    </tv-c-memory-dump-view>
+    <tr-c-a-memory-dump-view id="memory_dump_view">
+    </tr-c-a-memory-dump-view>
   </template>
   <script>
   'use strict';
@@ -21,10 +21,10 @@
     set selection(selection) {
       if (selection.length !== 1)
         throw new Error('Only supports a single global memory dump');
-      if (!(selection[0] instanceof tv.c.trace_model.GlobalMemoryDump))
+      if (!(selection[0] instanceof tr.model.GlobalMemoryDump))
         throw new Error('Only supports global memory dumps');
       this.currentSelection_ = selection;
-      this.$.memory_dump_view.processMemoryDumps = tv.b.dictionaryValues(
+      this.$.memory_dump_view.processMemoryDumps = tr.b.dictionaryValues(
           selection[0].processMemoryDumps);
     },
 
diff --git a/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view_test.html
index ed97dda..6af0f1f 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_global_memory_dump_sub_view_test.html
@@ -13,9 +13,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var createTestGlobalMemoryDump = tv.c.analysis.createTestGlobalMemoryDump;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var createTestGlobalMemoryDump = tr.c.analysis.createTestGlobalMemoryDump;
 
   test('instantiate', function() {
     var globalMemoryDump = createTestGlobalMemoryDump();
@@ -24,7 +24,7 @@
     selection.push(globalMemoryDump);
 
     var viewEl = document.createElement(
-        'tv-c-single-global-memory-dump-sub-view');
+        'tr-c-a-single-global-memory-dump-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view.html
index 7358c7d..58b9c28 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
 
-<polymer-element name="tv-c-single-instant-event-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-instant-event-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -29,7 +29,7 @@
 
     set selection(selection) {
       this.$.content.textContent = '';
-      var realView = document.createElement('tv-c-a-single-event-sub-view');
+      var realView = document.createElement('tr-c-a-single-event-sub-view');
       realView.setSelectionWithoutErrorChecks(selection);
 
       this.$.content.appendChild(realView);
diff --git a/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view_test.html
index 653253a..b9f67bc 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_instant_event_sub_view_test.html
@@ -8,23 +8,22 @@
 <link rel="import" href="/core/analysis/analysis_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Thread = tv.c.trace_model.Thread;
-  var Selection = tv.c.Selection;
-  var trace_model = tv.c.trace_model;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Thread = tr.model.Thread;
+  var Selection = tr.c.Selection;
 
   test('analyzeSelectionWithSingleEvent', function() {
     var model = new Model();
     var p52 = model.getOrCreateProcess(52);
     var t53 = p52.getOrCreateThread(53);
 
-    var ie = new trace_model.ProcessInstantEvent('cat', 'title', 7, 10, {});
+    var ie = new tr.model.ProcessInstantEvent('cat', 'title', 7, 10, {});
     ie.duration = 20;
     p52.instantEvents.push(ie);
 
@@ -33,7 +32,8 @@
     selection.push(ie);
     assert.equal(selection.length, 1);
 
-    var subView = document.createElement('tv-c-single-instant-event-sub-view');
+    var subView = document.createElement(
+        'tr-c-a-single-instant-event-sub-view');
     subView.selection = selection;
 
     this.addHTMLOutput(subView);
diff --git a/trace-viewer/trace_viewer/core/analysis/single_interaction_record_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_interaction_record_sub_view.html
index c0a4cae..bb8e546 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_interaction_record_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_interaction_record_sub_view.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
 
-<polymer-element name="tv-c-single-interaction-record-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-interaction-record-sub-view"
+    extends="tr-c-a-sub-view">
   <script>
   'use strict';
 
@@ -20,7 +20,7 @@
 
     set selection(selection) {
       this.textContent = '';
-      var realView = document.createElement('tv-c-a-single-event-sub-view');
+      var realView = document.createElement('tr-c-a-single-event-sub-view');
 
       this.appendChild(realView);
       realView.setSelectionWithoutErrorChecks(selection);
@@ -31,7 +31,7 @@
     get relatedEventsToHighlight() {
       if (!this.currentSelection_)
         return undefined;
-      return new tv.c.Selection(this.currentSelection_[0].associatedEvents);
+      return new tr.c.Selection(this.currentSelection_[0].associatedEvents);
     }
   });
   </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view.html
index 32fc98f..8d7b9ba 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view.html
@@ -10,10 +10,10 @@
 <link rel="import" href="/core/analysis/generic_object_view.html">
 <link rel="import" href="/core/analysis/object_instance_view.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
-<polymer-element name="tv-c-single-object-instance-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-object-instance-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
@@ -58,7 +58,7 @@
       if (this.$.content.children.length === 0)
         return false;
       if (this.$.content.children[0] instanceof
-          tv.c.analysis.ObjectInstanceView)
+          tr.c.analysis.ObjectInstanceView)
         return this.$.content.children[0].requiresTallView;
     },
 
@@ -69,14 +69,14 @@
     set selection(selection) {
       if (selection.length !== 1)
         throw new Error('Only supports single item selections');
-      if (!(selection[0] instanceof tv.c.trace_model.ObjectInstance))
+      if (!(selection[0] instanceof tr.model.ObjectInstance))
         throw new Error('Only supports object instances');
 
       this.$.content.textContent = '';
       this.currentSelection_ = selection;
 
       var instance = selection[0];
-      var typeInfo = tv.c.analysis.ObjectInstanceView.getTypeInfo(
+      var typeInfo = tr.c.analysis.ObjectInstanceView.getTypeInfo(
           instance.category, instance.typeName);
       if (typeInfo) {
         var customView = new typeInfo.constructor();
@@ -107,8 +107,8 @@
       this.$.content.innerHTML = html;
       var snapshotsEl = this.$.content.querySelector('#snapshots');
       instance.snapshots.forEach(function(snapshot) {
-        var snapshotLink = document.createElement('tv-c-analysis-link');
-        snapshotLink.selection = new tv.c.Selection(snapshot);
+        var snapshotLink = document.createElement('tr-c-a-analysis-link');
+        snapshotLink.selection = new tr.c.Selection(snapshot);
         snapshotsEl.appendChild(snapshotLink);
       });
     }
diff --git a/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view_test.html
index 8066b65..71060c9 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_object_instance_sub_view_test.html
@@ -8,25 +8,23 @@
 <link rel="import" href="/core/analysis/single_object_instance_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TraceModel = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var ObjectInstance = tv.c.trace_model.ObjectInstance;
+tr.b.unittest.testSuite(function() {
+  var ObjectInstance = tr.model.ObjectInstance;
 
   test('analyzeSelectionWithObjectInstanceUnknownType', function() {
     var i10 = new ObjectInstance({}, '0x1000', 'cat', 'someUnhandledName', 10);
     var s10 = i10.addSnapshot(10, {foo: 1});
     var s20 = i10.addSnapshot(20, {foo: 2});
 
-    var selection = new Selection();
+    var selection = new tr.c.Selection();
     selection.push(i10);
 
-    var view = document.createElement('tv-c-single-object-instance-sub-view');
+    var view = document.createElement('tr-c-a-single-object-instance-sub-view');
     view.selection = selection;
     this.addHTMLOutput(view);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view.html
index 1363dc7..4497acc 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view.html
@@ -11,10 +11,10 @@
 <link rel="import" href="/core/analysis/object_instance_view.html">
 <link rel="import" href="/core/analysis/object_snapshot_view.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
-<polymer-element name="tv-c-single-object-snapshot-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-object-snapshot-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     #args {
@@ -54,7 +54,7 @@
     get requiresTallView() {
       if (this.children.length === 0)
         return false;
-      if (this.children[0] instanceof tv.c.analysis.ObjectSnapshotView)
+      if (this.children[0] instanceof tr.c.analysis.ObjectSnapshotView)
         return this.children[0].requiresTallView;
     },
 
@@ -65,7 +65,7 @@
     set selection(selection) {
       if (selection.length !== 1)
         throw new Error('Only supports single item selections');
-      if (!(selection[0] instanceof tv.c.trace_model.ObjectSnapshot))
+      if (!(selection[0] instanceof tr.model.ObjectSnapshot))
         throw new Error('Only supports object instances');
 
       this.textContent = '';
@@ -73,7 +73,7 @@
 
       var snapshot = selection[0];
 
-      var typeInfo = tv.c.analysis.ObjectSnapshotView.getTypeInfo(
+      var typeInfo = tr.c.analysis.ObjectSnapshotView.getTypeInfo(
           snapshot.objectInstance.category, snapshot.objectInstance.typeName);
       if (typeInfo) {
         var customView = new typeInfo.constructor();
@@ -89,17 +89,17 @@
 
       var html = '';
       html += '<div class="title">Snapshot of <a id="instance-link"></a> @ ' +
-          tv.c.analysis.tsString(snapshot.ts) + '</div>\n';
+          tr.b.units.tsString(snapshot.ts) + '</div>\n';
       html += '<table>';
       html += '<tr>';
       html += '<tr><td>args:</td><td id="args"></td></tr>\n';
       html += '</table>';
       this.innerHTML = html;
 
-      var instanceLinkEl = document.createElement('tv-c-analysis-link');
-      instanceLinkEl.selection = new tv.c.Selection(instance);
+      var instanceLinkEl = document.createElement('tr-c-a-analysis-link');
+      instanceLinkEl.selection = new tr.c.Selection(instance);
 
-      // TODO(nduca): tv.ui.decoreate doesn't work when subclassed. So,
+      // TODO(nduca): tr.ui.decoreate doesn't work when subclassed. So,
       // replace the template element.
       var tmp = this.querySelector('#instance-link');
       tmp.parentElement.replaceChild(instanceLinkEl, tmp);
@@ -107,7 +107,7 @@
       var argsEl = this.querySelector('#args');
       argsEl.textContent = '';
       var objectView =
-          document.createElement('tv-c-analysis-generic-object-view');
+          document.createElement('tr-c-a-generic-object-view');
       objectView.object = snapshot.args;
       argsEl.appendChild(objectView);
     }
diff --git a/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view_test.html
index ce9166c..efeb985 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_object_snapshot_sub_view_test.html
@@ -8,26 +8,22 @@
 <link rel="import" href="/core/analysis/single_object_snapshot_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TraceModel = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var ObjectInstance = tv.c.trace_model.ObjectInstance;
-
+tr.b.unittest.testSuite(function() {
   test('instantiate_snapshotView', function() {
-    var i10 = new tv.c.trace_model.ObjectInstance(
+    var i10 = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'name', 10);
     var s10 = i10.addSnapshot(10, {foo: 1});
     i10.updateBounds();
 
-    var selection = new Selection();
+    var selection = new tr.c.Selection();
     selection.push(s10);
 
-    var view = document.createElement('tv-c-single-object-snapshot-sub-view');
+    var view = document.createElement('tr-c-a-single-object-snapshot-sub-view');
     view.selection = selection;
     this.addHTMLOutput(view);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view.html
index 2185904..3ab5226 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view.html
@@ -8,11 +8,11 @@
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/memory_dump_view.html">
 
-<polymer-element name="tv-c-single-process-memory-dump-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-process-memory-dump-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
-    <tv-c-memory-dump-view id="memory_dump_view">
-    </tv-c-memory-dump-view>
+    <tr-c-a-memory-dump-view id="memory_dump_view">
+    </tr-c-a-memory-dump-view>
   </template>
   <script>
   'use strict';
@@ -21,7 +21,7 @@
     set selection(selection) {
       if (selection.length !== 1)
         throw new Error('Only supports a single process memory dump');
-      if (!(selection[0] instanceof tv.c.trace_model.ProcessMemoryDump))
+      if (!(selection[0] instanceof tr.model.ProcessMemoryDump))
         throw new Error('Only supports process memory dumps');
       this.currentSelection_ = selection;
       this.$.memory_dump_view.processMemoryDumps = [selection[0]];
diff --git a/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view_test.html
index 6682160..bd7b871 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_process_memory_dump_sub_view_test.html
@@ -13,9 +13,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var createTestProcessMemoryDump = tv.c.analysis.createTestProcessMemoryDump;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var createTestProcessMemoryDump = tr.c.analysis.createTestProcessMemoryDump;
 
   test('instantiate', function() {
     var processMemoryDump = createTestProcessMemoryDump();
@@ -24,7 +24,7 @@
     selection.push(processMemoryDump);
 
     var viewEl = document.createElement(
-        'tv-c-single-process-memory-dump-sub-view');
+        'tr-c-a-single-process-memory-dump-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view.html
index 17f72c7..b05b4fc 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view.html
@@ -6,19 +6,19 @@
 -->
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 <link rel="import" href="/core/analysis/stack_frame.html">
-<link rel="import" href="/core/analysis/time_stamp.html">
+<link rel="import" href="/base/units/time_stamp_span.html">
 
-<polymer-element name="tv-c-single-sample-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-sample-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
       display: flex;
     }
     </style>
-    <tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+    <tr-b-ui-table id="content"></tr-b-ui-table>
   </template>
   <script>
   'use strict';
@@ -68,10 +68,10 @@
 
       rows.push({
           title: 'Sample time',
-          value: tv.c.analysis.createTimeStamp(sample.start)
+          value: tr.b.units.createTimeStampSpan(sample.start)
       });
 
-      var sfEl = document.createElement('tv-c-a-stack-frame');
+      var sfEl = document.createElement('tr-c-a-stack-frame');
       sfEl.stackFrame = sample.leafStackFrame;
       rows.push({
         title: 'Stack trace',
@@ -82,4 +82,4 @@
     }
   });
   </script>
-</polymer-element>
\ No newline at end of file
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view_test.html
index 758f6b3..91ed335 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_sample_sub_view_test.html
@@ -9,16 +9,16 @@
 <link rel="import" href="/core/analysis/single_sample_sub_view.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Model = tv.c.TraceModel;
-  var Selection = tv.c.Selection;
-  var StubAnalysisResults = tv.c.analysis.StubAnalysisResults;
-  var newSampleNamed = tv.c.test_utils.newSampleNamed;
+tr.b.unittest.testSuite(function() {
+  var Model = tr.Model;
+  var Selection = tr.c.Selection;
+  var StubAnalysisResults = tr.c.analysis.StubAnalysisResults;
+  var newSampleNamed = tr.c.test_utils.newSampleNamed;
 
   test('instantiate_withSingleSample', function() {
     var model = new Model();
@@ -38,12 +38,12 @@
     selection.push(t53.samples[0]);
     assert.equal(selection.length, 1);
 
-    var view = document.createElement('tv-c-single-sample-sub-view');
+    var view = document.createElement('tr-c-a-single-sample-sub-view');
     view.selection = selection;
     this.addHTMLOutput(view);
 
-    var table = tv.b.findDeepElementMatching(
-        view, 'tracing-analysis-nested-table');
+    var table = tr.b.findDeepElementMatching(
+        view, 'tr-b-ui-table');
 
     var rows = table.tableRows;
     assert.equal(rows.length, 3);
diff --git a/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view.html
index 8a5dd33..3e29dbc 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view.html
@@ -7,26 +7,26 @@
 
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/single_event_sub_view.html">
-<link rel="import" href="/core/analysis/related_flows.html">
+<link rel="import" href="/core/analysis/related_events.html">
 
-<polymer-element name="tv-c-a-single-thread-slice-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-thread-slice-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     :host {
       display: flex;
       flex-direction: row;
     }
-    #flows {
+    #events {
       display: flex;
       flex-direction: column;
     }
 
     </style>
-    <tv-c-a-single-event-sub-view id="content"></tv-c-a-single-event-sub-view>
-    <div id="flows">
-      <tv-c-a-related-flows id="rflows">
-      </tv-c-a-related-flows>
+    <tr-c-a-single-event-sub-view id="content"></tr-c-a-single-event-sub-view>
+    <div id="events">
+      <tr-c-a-related-events id="relatedEvents">
+      </tr-c-a-related-events>
     </div>
   </template>
 
@@ -40,22 +40,11 @@
 
     set selection(selection) {
       this.$.content.selection = selection;
-      var hasFlows = false;
-      var slice;
-      if (selection) {
-        slice = selection[0];
-        hasFlows = slice.inFlowEvents.length !== 0 ||
-            slice.outFlowEvents.length !== 0;
-      }
-      if (hasFlows) {
-        this.$.rflows.style.display = '';
-        this.$.rflows.setFlows(
-          new tv.c.Selection(slice.inFlowEvents),
-          new tv.c.Selection(slice.outFlowEvents));
-      } else {
-        this.$.rflows.style.display = 'none';
-        this.$.rflows.clearFlows();
-      }
+      this.$.relatedEvents.addRelatedEvents(selection);
+      if (this.$.relatedEvents.hasRelatedEvents())
+        this.$.relatedEvents.style.display = '';
+      else
+        this.$.relatedEvents.style.display = 'none';
     }
   });
   </script>
diff --git a/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view_test.html
index 8575b7c..dda5149 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_thread_slice_sub_view_test.html
@@ -8,32 +8,33 @@
 <link rel="import" href="/core/analysis/single_thread_slice_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/thread_slice.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newSliceEx = tv.c.test_utils.newSliceEx;
-  var newFlowEventEx = tv.c.test_utils.newFlowEventEx;
+tr.b.unittest.testSuite(function() {
+  var newSliceEx = tr.c.test_utils.newSliceEx;
+  var newFlowEventEx = tr.c.test_utils.newFlowEventEx;
 
   test('instantiate', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
     t53.sliceGroup.pushSlice(
         newSliceEx({title: 'a', start: 0.0, duration: 0.5}));
     t53.sliceGroup.createSubSlices();
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(t53.sliceGroup.slices[0]);
 
-    var viewEl = document.createElement('tv-c-a-single-thread-slice-sub-view');
+    var viewEl = document.createElement('tr-c-a-single-thread-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
 
   test('instantiateWithFlowEvent', function() {
-    var m = tv.c.test_utils.newModel(function(m) {
+    var m = tr.c.test_utils.newModel(function(m) {
       m.p1 = m.getOrCreateProcess(1);
 
       m.t2 = m.p1.getOrCreateThread(2);
@@ -41,11 +42,14 @@
       m.t4 = m.p1.getOrCreateThread(4);
 
       m.sA = m.t2.sliceGroup.pushSlice(
-          newSliceEx({title: 'a', start: 0, end: 5}));
+          newSliceEx({title: 'a', start: 0, end: 5,
+                      type: tr.model.ThreadSlice}));
       m.sB = m.t3.sliceGroup.pushSlice(
-          newSliceEx({title: 'b', start: 10, end: 15}));
+          newSliceEx({title: 'b', start: 10, end: 15,
+                      type: tr.model.ThreadSlice}));
       m.sC = m.t4.sliceGroup.pushSlice(
-          newSliceEx({title: 'c', start: 20, end: 20}));
+          newSliceEx({title: 'c', start: 20, end: 20,
+                      type: tr.model.ThreadSlice}));
 
       m.t2.createSubSlices();
       m.t3.createSubSlices();
@@ -63,10 +67,10 @@
       });
     });
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(m.sA);
 
-    var viewEl = document.createElement('tv-c-a-single-thread-slice-sub-view');
+    var viewEl = document.createElement('tr-c-a-single-thread-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view.html b/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view.html
index dafba70..34574f7 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view.html
@@ -11,11 +11,11 @@
 <link rel="import" href="/core/analysis/analysis_link.html">
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
-<link rel="import" href="/core/analysis/util.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/base/units/util.html">
+<link rel="import" href="/model/model.html">
 
-<polymer-element name="tv-c-single-thread-time-slice-sub-view"
-    extends="tracing-analysis-sub-view">
+<polymer-element name="tr-c-a-single-thread-time-slice-sub-view"
+    extends="tr-c-a-sub-view">
   <template>
     <style>
     table {
@@ -94,7 +94,7 @@
     set selection(selection) {
       if (selection.length !== 1)
         throw new Error('Only supports single slices');
-      if (!(selection[0] instanceof tv.c.trace_model.ThreadTimeSlice))
+      if (!(selection[0] instanceof tr.model.ThreadTimeSlice))
         throw new Error('Only supports thread time slices');
 
       this.currentSelection_ = selection;
@@ -104,7 +104,7 @@
 
       var shadowRoot = this.shadowRoot;
       shadowRoot.querySelector('#state').textContent = timeSlice.title;
-      var stateColor = tv.b.ui.getColorPalette()[timeSlice.colorId];
+      var stateColor = tr.b.ui.getColorPalette()[timeSlice.colorId];
       shadowRoot.querySelector('#state').style.backgroundColor = stateColor;
 
       shadowRoot.querySelector('#process-name').textContent =
@@ -113,17 +113,17 @@
           thread.userFriendlyName;
 
       shadowRoot.querySelector('#start').textContent =
-          tv.c.analysis.tsString(timeSlice.start);
+          tr.b.units.tsString(timeSlice.start);
       shadowRoot.querySelector('#duration').textContent =
-          tv.c.analysis.tsString(timeSlice.duration);
+          tr.b.units.tsString(timeSlice.duration);
       var onCpuEl = shadowRoot.querySelector('#on-cpu');
       onCpuEl.textContent = '';
       var runningInsteadEl = shadowRoot.querySelector('#running-instead');
       if (timeSlice.cpuOnWhichThreadWasRunning) {
         runningInsteadEl.parentElement.removeChild(runningInsteadEl);
 
-        var cpuLink = document.createElement('tv-c-analysis-link');
-        cpuLink.selection = new tv.c.Selection(
+        var cpuLink = document.createElement('tr-c-a-analysis-link');
+        cpuLink.selection = new tr.c.Selection(
             timeSlice.getAssociatedCpuSlice());
         cpuLink.textContent =
             timeSlice.cpuOnWhichThreadWasRunning.userFriendlyName;
@@ -133,8 +133,8 @@
 
         var cpuSliceThatTookCpu = timeSlice.getCpuSliceThatTookCpu();
         if (cpuSliceThatTookCpu) {
-          var cpuLink = document.createElement('tv-c-analysis-link');
-          cpuLink.selection = new tv.c.Selection(cpuSliceThatTookCpu);
+          var cpuLink = document.createElement('tr-c-a-analysis-link');
+          cpuLink.selection = new tr.c.Selection(cpuSliceThatTookCpu);
           if (cpuSliceThatTookCpu.thread)
             cpuLink.textContent = cpuSliceThatTookCpu.thread.userFriendlyName;
           else
@@ -146,9 +146,9 @@
       }
 
       var argsEl = shadowRoot.querySelector('#args');
-      if (tv.b.dictionaryKeys(timeSlice.args).length > 0) {
+      if (tr.b.dictionaryKeys(timeSlice.args).length > 0) {
         var argsView =
-            document.createElement('tv-c-analysis-generic-object-view');
+            document.createElement('tr-c-a-generic-object-view');
         argsView.object = timeSlice.args;
 
         argsEl.parentElement.style.display = '';
diff --git a/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view_test.html b/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view_test.html
index aa3788d..d3d0fe0 100644
--- a/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/single_thread_time_slice_sub_view_test.html
@@ -5,14 +5,14 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/analysis/single_thread_time_slice_sub_view.html">
 <link rel="import" href="/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   function createBasicModel() {
     var lines = [
       'Android.launcher-584   [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
@@ -24,7 +24,7 @@
       '       Binder_1-217   [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
     ];
 
-    return new tv.c.TraceModel(lines.join('\n'), false);
+    return new tr.Model(lines.join('\n'), false);
   }
 
   test('runningSlice', function() {
@@ -39,8 +39,9 @@
 
     var thread = m.findAllThreadsNamed('Binder_1')[0];
 
-    var view = document.createElement('tv-c-single-thread-time-slice-sub-view');
-    var selection = new tv.c.Selection();
+    var view = document.createElement(
+        'tr-c-a-single-thread-time-slice-sub-view');
+    var selection = new tr.c.Selection();
     selection.push(thread.timeSlices[0]);
     view.selection = selection;
     this.addHTMLOutput(view);
@@ -52,7 +53,7 @@
       assert.equal(e.selection[0], binderSlice);
       didSelectionChangeHappen = true;
     });
-    view.shadowRoot.querySelector('tv-c-analysis-link').click();
+    view.shadowRoot.querySelector('tr-c-a-analysis-link').click();
     assert.isTrue(didSelectionChangeHappen);
   });
 
@@ -68,8 +69,9 @@
 
     var thread = m.findAllThreadsNamed('Binder_1')[0];
 
-    var view = document.createElement('tv-c-single-thread-time-slice-sub-view');
-    var selection = new tv.c.Selection();
+    var view = document.createElement(
+        'tr-c-a-single-thread-time-slice-sub-view');
+    var selection = new tr.c.Selection();
     selection.push(thread.timeSlices[1]);
     view.selection = selection;
     this.addHTMLOutput(view);
@@ -81,7 +83,7 @@
       assert.equal(e.selection[0], launcherSlice);
       didSelectionChangeHappen = true;
     });
-    view.shadowRoot.querySelector('tv-c-analysis-link').click();
+    view.shadowRoot.querySelector('tr-c-a-analysis-link').click();
     assert.isTrue(didSelectionChangeHappen);
   });
 });
diff --git a/trace-viewer/trace_viewer/core/analysis/size_span.html b/trace-viewer/trace_viewer/core/analysis/size_span.html
deleted file mode 100644
index f34a987..0000000
--- a/trace-viewer/trace_viewer/core/analysis/size_span.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2015 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.
--->
-<polymer-element name="tv-c-a-size-span">
-  <template>
-    <style>
-    :host {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-    }
-    </style>
-    <span id="content"></span>
-  </template>
-  <script>
-  'use strict';
-
-  Polymer({
-    ready: function() {
-      this.$.content.textContent = String.fromCharCode(9888);
-      this.numBytes_ = undefined;
-    },
-
-    get numBytes() {
-      return this.numBytes_;
-    },
-
-    set numBytes(numBytes) {
-      this.numBytes_ = numBytes;
-
-      var prefixes = ['', 'Ki', 'Mi', 'Gi', 'Ti'];
-      var i = 0;
-      while (numBytes >= 1024 && i < prefixes.length - 1) {
-        numBytes /= 1024;
-        i++;
-      }
-      var sizeString = numBytes.toFixed(1) + ' ' + prefixes[i] + 'B';
-
-      this.$.content.textContent = sizeString;
-    },
-
-    get stringContent() {
-      return this.$.content.textContent;
-    }
-  });
-  </script>
-</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/stack_frame.html b/trace-viewer/trace_viewer/core/analysis/stack_frame.html
index e83e8b2..6f43bb1 100644
--- a/trace-viewer/trace_viewer/core/analysis/stack_frame.html
+++ b/trace-viewer/trace_viewer/core/analysis/stack_frame.html
@@ -6,7 +6,7 @@
 -->
 <link rel="import" href="/core/analysis/generic_object_view.html">
 
-<polymer-element name="tv-c-a-stack-frame">
+<polymer-element name="tr-c-a-stack-frame">
   <template>
     <style>
     :host {
@@ -15,8 +15,8 @@
       align-items: center;
     }
     </style>
-    <tv-c-analysis-generic-object-view id="ov">
-    </tv-c-analysis-generic-object-view>
+    <tr-c-a-generic-object-view id="ov">
+    </tr-c-a-generic-object-view>
   </template>
   <script>
   'use strict';
diff --git a/trace-viewer/trace_viewer/core/analysis/stack_frame_test.html b/trace-viewer/trace_viewer/core/analysis/stack_frame_test.html
index d13b232..0aa0b45 100644
--- a/trace-viewer/trace_viewer/core/analysis/stack_frame_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/stack_frame_test.html
@@ -9,14 +9,14 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
-    var model = new tv.c.TraceModel();
-    var fA = tv.c.test_utils.newStackTrace(model, 'cat', ['a1', 'a2', 'a3']);
+    var model = new tr.Model();
+    var fA = tr.c.test_utils.newStackTrace(model, 'cat', ['a1', 'a2', 'a3']);
 
-    var stackFrameView = document.createElement('tv-c-a-stack-frame');
+    var stackFrameView = document.createElement('tr-c-a-stack-frame');
     stackFrameView.stackFrame = fA;
     this.addHTMLOutput(stackFrameView);
   });
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/core/analysis/stub_analysis_results.html b/trace-viewer/trace_viewer/core/analysis/stub_analysis_results.html
index 0666794..1f0d9ff 100644
--- a/trace-viewer/trace_viewer/core/analysis/stub_analysis_results.html
+++ b/trace-viewer/trace_viewer/core/analysis/stub_analysis_results.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.analysis', function() {
+tr.exportTo('tr.c.analysis', function() {
   function StubAnalysisResults() {
     this.headers = [];
     this.info = [];
diff --git a/trace-viewer/trace_viewer/core/analysis/stub_analysis_table.html b/trace-viewer/trace_viewer/core/analysis/stub_analysis_table.html
index 1bb17db..203204c 100644
--- a/trace-viewer/trace_viewer/core/analysis/stub_analysis_table.html
+++ b/trace-viewer/trace_viewer/core/analysis/stub_analysis_table.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.analysis', function() {
+tr.exportTo('tr.c.analysis', function() {
   function StubAnalysisTable() {
     this.ownerDocument_ = document;
     this.nodes_ = [];
diff --git a/trace-viewer/trace_viewer/core/analysis/tab_view_test.html b/trace-viewer/trace_viewer/core/analysis/tab_view_test.html
index 7c2092c..63b8c0e 100644
--- a/trace-viewer/trace_viewer/core/analysis/tab_view_test.html
+++ b/trace-viewer/trace_viewer/core/analysis/tab_view_test.html
@@ -22,7 +22,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var THIS_DOC = document._currentScript.ownerDocument;
 
   test('instantiate', function() {
diff --git a/trace-viewer/trace_viewer/core/analysis/time_span.html b/trace-viewer/trace_viewer/core/analysis/time_span.html
deleted file mode 100644
index 5687685..0000000
--- a/trace-viewer/trace_viewer/core/analysis/time_span.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 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="import" href="/core/analysis/util.html">
-
-<script>
-'use strict';
-tv.exportTo('tv.c.analysis', function() {
-  function createTimeSpan(duration) {
-    if (duration === undefined)
-      return '';
-    var span = document.createElement('tv-c-a-time-span');
-    span.duration = duration;
-    return span;
-  }
-  return {
-    createTimeSpan: createTimeSpan
-  };
-});
-</script>
-
-<polymer-element name="tv-c-a-time-span">
-  <template>
-    <style>
-    :host {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-    }
-    #warning {
-      margin-left: 4px;
-      font-size: 66%;
-    }
-    </style>
-    <span id="content"></span>
-    <span id="warning" style="display:none">&#9888;</span>
-  </template>
-  <script>
-  'use strict';
-
-  Polymer({
-    ready: function() {
-      this.warning_ = undefined;
-      this.duration_ = undefined;
-    },
-
-    get duration() {
-      return this.duration_;
-    },
-
-    set duration(duration) {
-      this.duration_ = duration;
-      this.$.content.textContent = tv.c.analysis.tsString(duration);
-    },
-
-    get warning() {
-      return this.warning_;
-    },
-
-    set warning(warning) {
-      this.warning_ = warning;
-      var warningEl = this.$.warning;
-      if (this.warning_) {
-        warningEl.title = warning;
-        warningEl.style.display = '';
-      } else {
-        warningEl.title = '';
-        warningEl.style.display = 'none';
-      }
-    }
-  });
-  </script>
-</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/time_span_test.html b/trace-viewer/trace_viewer/core/analysis/time_span_test.html
deleted file mode 100644
index 231204b..0000000
--- a/trace-viewer/trace_viewer/core/analysis/time_span_test.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 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="import" href="/core/analysis/time_span.html">
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() {
-  test('instantiate', function() {
-    var timeSpan = document.createElement('tv-c-a-time-span');
-    timeSpan.duration = 73;
-    this.addHTMLOutput(timeSpan);
-  });
-  test('instantiateWithWarning', function() {
-    var timeSpan = document.createElement('tv-c-a-time-span');
-    timeSpan.duration = 400;
-    timeSpan.warning = 'there is a problem with this time';
-    this.addHTMLOutput(timeSpan);
-  });
-
-  test('warningAndNonWarningHaveSimilarHeights', function() {
-    var spanA = document.createElement('tv-c-a-time-span');
-    spanA.duration = 400;
-
-    var spanB = document.createElement('tv-c-a-time-span');
-    spanB.duration = 400;
-    spanB.warning = 'there is a problem with this time';
-
-    var overall = document.createElement('div');
-    overall.style.display = 'flex';
-    overall.appendChild(spanA);
-    spanB.style.marginLeft = '4px';
-    overall.appendChild(spanB);
-    this.addHTMLOutput(overall);
-  });
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/analysis/time_stamp.html b/trace-viewer/trace_viewer/core/analysis/time_stamp.html
deleted file mode 100644
index 2b5a404..0000000
--- a/trace-viewer/trace_viewer/core/analysis/time_stamp.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2015 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="import" href="/core/analysis/util.html">
-
-<script>
-'use strict';
-tv.exportTo('tv.c.analysis', function() {
-  function createTimeStamp(timestamp) {
-    if (timestamp === undefined)
-      return '';
-    var span = document.createElement('tv-c-a-time-stamp');
-    span.timestamp = timestamp;
-    return span;
-  }
-  return {
-    createTimeStamp: createTimeStamp
-  };
-});
-</script>
-
-<polymer-element name="tv-c-a-time-stamp">
-  <template>
-  </template>
-  <script>
-  'use strict';
-
-  Polymer({
-    ready: function() {
-      this.timestamp_ = undefined;
-    },
-
-    get timestamp() {
-      return this.timestamp_;
-    },
-
-    set timestamp(timestamp) {
-      this.timestamp_ = timestamp;
-      this.shadowRoot.textContent = tv.c.analysis.tsString(timestamp);
-    }
-  });
-  </script>
-</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/time_stamp_test.html b/trace-viewer/trace_viewer/core/analysis/time_stamp_test.html
deleted file mode 100644
index aa9b074..0000000
--- a/trace-viewer/trace_viewer/core/analysis/time_stamp_test.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 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="import" href="/core/analysis/time_stamp.html">
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() {
-  test('instantiate', function() {
-    var timeStamp = document.createElement('tv-c-a-time-stamp');
-    timeStamp.timestamp = 73;
-    this.addHTMLOutput(timeStamp);
-  });
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/analysis/toggle_container.html b/trace-viewer/trace_viewer/core/analysis/toggle_container.html
deleted file mode 100644
index bf212bf..0000000
--- a/trace-viewer/trace_viewer/core/analysis/toggle_container.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 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.
--->
-
-<!--
-@fileoverview A basic container that shows and hides itself based on an
-event fired by a specified target.
--->
-
-<polymer-element name="tracing-analysis-toggle-container"
-    constructor="TracingAnalysisToggleContainer">
-  <template>
-    <style>
-      :host(:[visible]) {
-        display: flex;
-      }
-
-      :host(:not([visible])) {
-        display: none;
-      }
-
-      ::content > * {
-        flex: 0 1 auto;
-      }
-
-    </style>
-    <content></content>
-  </template>
-  <script>
-  'use strict';
-  Polymer({
-    /**
-     * The visible property governs wether the component displays
-     * it's contents or not.
-     */
-    publish: {
-      visible: {
-        value: false,
-        reflect: true
-      }
-    },
-
-    created: function() {
-      this.toggleListeners_ = [];
-    },
-
-    toggleVisible: function() {
-      this.visible = !this.visible;
-    },
-
-    setToggleListener: function(target, eventType) {
-      var listenerFunction = this.toggleVisible.bind(this);
-      target.addEventListener(eventType, listenerFunction, false);
-      this.toggleListeners_.push({
-        target: target,
-        eventType: eventType,
-        listenerFunction: listenerFunction
-      });
-    },
-
-    clearToggleListener: function(target, eventType) {
-      for (var i = 0; i < this.toggleListeners_.length; i++) {
-        var listener = this.toggleListeners_[i];
-        if (listener.target === target && listener.eventType === eventType) {
-          target.removeEventListener(listener.eventType,
-                                     listener.listenerFunction, false);
-          this.toggleListeners_.splice(i, 1);
-          return;
-        }
-      }
-    }
-  });
-  </script>
-</polymer-element>
diff --git a/trace-viewer/trace_viewer/core/analysis/toggle_container_test.html b/trace-viewer/trace_viewer/core/analysis/toggle_container_test.html
deleted file mode 100644
index 616ccd7..0000000
--- a/trace-viewer/trace_viewer/core/analysis/toggle_container_test.html
+++ /dev/null
@@ -1,135 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 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="import" href="/core/analysis/toggle_container.html">
-
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() {
-  var THIS_DOC = document._currentScript.ownerDocument;
-
-  test('instantiateVisibleProperty', function() {
-    var container = THIS_DOC.createElement('div');
-    var firstToggleContainer = new TracingAnalysisToggleContainer();
-    var secondToggleContainer = new TracingAnalysisToggleContainer();
-    var defaultSettingsToggleContainer = new TracingAnalysisToggleContainer();
-
-    var visibleChild = THIS_DOC.createElement('div');
-    var hiddenChild = THIS_DOC.createElement('div');
-    var defaultHiddenChild = THIS_DOC.createElement('div');
-
-    var button1 = THIS_DOC.createElement('button');
-    button1.textContent = '1: Toggle Visibility';
-
-    var button2 = THIS_DOC.createElement('button');
-    button2.textContent = '2: Toggle Visibility';
-
-    var button3 = THIS_DOC.createElement('button');
-    button3.textContent = '3: Toggle Visibility';
-
-    var buttonToggleAll = THIS_DOC.createElement('button');
-    buttonToggleAll.textContent = 'Toggle All';
-
-    visibleChild.textContent = '1: Should be visible';
-    hiddenChild.textContent = '2: Should not be visible';
-    defaultHiddenChild.textContent = '3: Should also not be visible';
-
-    firstToggleContainer.visible = true;
-    secondToggleContainer.visible = false;
-    // Default toggle container should have default visibility set to false.
-
-    firstToggleContainer.appendChild(visibleChild);
-    secondToggleContainer.appendChild(hiddenChild);
-    defaultSettingsToggleContainer.appendChild(defaultHiddenChild);
-
-    container.appendChild(button1);
-    container.appendChild(button2);
-    container.appendChild(button3);
-    container.appendChild(buttonToggleAll);
-    container.appendChild(firstToggleContainer);
-    container.appendChild(secondToggleContainer);
-    container.appendChild(defaultSettingsToggleContainer);
-
-    firstToggleContainer.setToggleListener(button1, 'click');
-    secondToggleContainer.setToggleListener(button2, 'click');
-    defaultSettingsToggleContainer.setToggleListener(button3, 'click');
-
-    firstToggleContainer.setToggleListener(buttonToggleAll, 'click');
-    secondToggleContainer.setToggleListener(buttonToggleAll, 'click');
-    defaultSettingsToggleContainer.setToggleListener(buttonToggleAll, 'click');
-
-    this.addHTMLOutput(container);
-  });
-
-  test('visiblePropertyReflection', function() {
-    var toggleContainer = new TracingAnalysisToggleContainer();
-
-    assert.isFalse(toggleContainer.hasAttribute('visible'));
-    toggleContainer.visible = true;
-    assert.isTrue(toggleContainer.hasAttribute('visible'));
-    toggleContainer.visible = false;
-    assert.isFalse(toggleContainer.hasAttribute('visible'));
-    toggleContainer.setAttribute('visible', 'true');
-    assert.isTrue(toggleContainer.visible);
-    toggleContainer.removeAttribute('visible');
-    assert.isFalse(toggleContainer.visible);
-  });
-
-  test('setAndClearToggleListener', function() {
-    var toggleContainer = new TracingAnalysisToggleContainer();
-
-    var firstTarget = THIS_DOC.createElement('div');
-    var secondTarget = THIS_DOC.createElement('div');
-    var invalidTarget = THIS_DOC.createElement('div');
-    toggleContainer.setToggleListener(firstTarget, 'click');
-    toggleContainer.setToggleListener(secondTarget, 'click');
-
-    var clickEvent = new MouseEvent('click', {
-      'view': window,
-      'bubbles': true,
-      'cancelable': true
-    });
-
-    firstTarget.dispatchEvent(clickEvent);
-    assert.isTrue(toggleContainer.visible);
-
-    firstTarget.dispatchEvent(clickEvent);
-    assert.isFalse(toggleContainer.visible);
-
-    secondTarget.dispatchEvent(clickEvent);
-    assert.isTrue(toggleContainer.visible);
-
-    secondTarget.dispatchEvent(clickEvent);
-    assert.isFalse(toggleContainer.visible);
-
-    toggleContainer.clearToggleListener(firstTarget, 'click');
-    firstTarget.dispatchEvent(clickEvent);
-    // This event should not toggle the state.
-    assert.isFalse(toggleContainer.visible);
-
-    secondTarget.dispatchEvent(clickEvent);
-    // This event should toggle the state.
-    assert.isTrue(toggleContainer.visible);
-
-    toggleContainer.clearToggleListener(invalidTarget, 'click');
-    secondTarget.dispatchEvent(clickEvent);
-    // This event should toggle the state.
-    assert.isFalse(toggleContainer.visible);
-
-    toggleContainer.clearToggleListener(secondTarget, 'invalidEventName');
-    secondTarget.dispatchEvent(clickEvent);
-    // This event should toggle the state.
-    assert.isTrue(toggleContainer.visible);
-
-    toggleContainer.clearToggleListener(secondTarget, 'click');
-    secondTarget.dispatchEvent(clickEvent);
-    // This event should not toggle the state as we've removed the listener.
-    assert.isTrue(toggleContainer.visible);
-  });
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/analysis/util.html b/trace-viewer/trace_viewer/core/analysis/util.html
deleted file mode 100644
index c4bdf01..0000000
--- a/trace-viewer/trace_viewer/core/analysis/util.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!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="import" href="/base/base.html">
-<script>
-'use strict';
-
-/**
- * @fileoverview Helper functions for use in selection_analysis files.
- */
-tv.exportTo('tv.c.analysis', function() {
-  function tsString(ts) {
-    return Number(tsRound(ts))
-        .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' ms';
-  }
-
-  function tsRound(ts) {
-    return Math.round(ts * 1000.0) / 1000.0;
-  }
-
-  return {
-    tsString: tsString,
-    tsRound: tsRound
-  };
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/auditor.html b/trace-viewer/trace_viewer/core/auditor.html
index 590f5dd..60a33c9 100644
--- a/trace-viewer/trace_viewer/core/auditor.html
+++ b/trace-viewer/trace_viewer/core/auditor.html
@@ -12,7 +12,7 @@
 /**
  * @fileoverview Base class for auditors.
  */
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   function Auditor(model) {
   }
 
@@ -33,10 +33,10 @@
     }
   };
 
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
   options.defaultMetadata = {};
   options.mandatoryBaseClass = Auditor;
-  tv.b.decorateExtensionRegistry(Auditor, options);
+  tr.b.decorateExtensionRegistry(Auditor, options);
 
   return {
     Auditor: Auditor
diff --git a/trace-viewer/trace_viewer/core/brushing_state.html b/trace-viewer/trace_viewer/core/brushing_state.html
index e66e78d..248656a 100644
--- a/trace-viewer/trace_viewer/core/brushing_state.html
+++ b/trace-viewer/trace_viewer/core/brushing_state.html
@@ -7,17 +7,17 @@
 
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.exportTo('tr.c', function() {
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
 
   function BrushingState() {
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
     this.selection_ = new Selection();
     this.findMatches_ = new Selection();
     this.analysisViewRelatedEvents_ = new Selection();
diff --git a/trace-viewer/trace_viewer/core/brushing_state_test.html b/trace-viewer/trace_viewer/core/brushing_state_test.html
index 12756ed..8b6acac 100644
--- a/trace-viewer/trace_viewer/core/brushing_state_test.html
+++ b/trace-viewer/trace_viewer/core/brushing_state_test.html
@@ -13,14 +13,14 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+tr.b.unittest.testSuite(function() {
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
 
   function newSimpleModel() {
-    return tv.c.test_utils.newModel(function(m) {
+    return tr.c.test_utils.newModel(function(m) {
       m.p1 = m.getOrCreateProcess(1);
       m.t2 = m.p1.getOrCreateThread(2);
 
@@ -36,7 +36,7 @@
   test('brushingStateSimple', function() {
     var m = newSimpleModel();
 
-    var bs = new tv.c.BrushingState();
+    var bs = new tr.c.BrushingState();
     bs.selection = new Selection([m.sA]);
 
     bs.applyToModelSelectionState(m);
@@ -48,7 +48,7 @@
   test('brushingStateWithSimpleHighlight', function() {
     var m = newSimpleModel();
 
-    var bs = new tv.c.BrushingState();
+    var bs = new tr.c.BrushingState();
     bs.selection = new Selection([m.sA]);
     bs.findMatches = new Selection([m.sA, m.sB]);
 
@@ -65,7 +65,7 @@
   test('brushingTransfer', function() {
     var m = newSimpleModel();
 
-    var bs = new tv.c.BrushingState();
+    var bs = new tr.c.BrushingState();
     bs.selection = new Selection([m.sA]);
 
     var bs2 = bs.clone();
@@ -85,7 +85,7 @@
   test('equality', function() {
     var m = newSimpleModel();
 
-    var bs = new tv.c.BrushingState();
+    var bs = new tr.c.BrushingState();
     bs.selection = new Selection([m.sA]);
     bs.findMatches = new Selection([m.sB]);
     bs.applyToModelSelectionState = new Selection([m.sC]);
diff --git a/trace-viewer/trace_viewer/core/constants.html b/trace-viewer/trace_viewer/core/constants.html
index 2fb03c4..253d0b3 100644
--- a/trace-viewer/trace_viewer/core/constants.html
+++ b/trace-viewer/trace_viewer/core/constants.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   var constants = {
     HEADING_WIDTH: 250
   };
diff --git a/trace-viewer/trace_viewer/core/draw_helpers.html b/trace-viewer/trace_viewer/core/draw_helpers.html
index cd0f477..f5bcee1 100644
--- a/trace-viewer/trace_viewer/core/draw_helpers.html
+++ b/trace-viewer/trace_viewer/core/draw_helpers.html
@@ -16,11 +16,11 @@
  * @fileoverview Provides various helper methods for drawing to a provided
  * canvas.
  */
-tv.exportTo('tv.c', function() {
-  var elidedTitleCache = new tv.c.ElidedTitleCache();
-  var palette = tv.b.ui.getColorPalette();
-  var EventPresenter = tv.c.EventPresenter;
-  var blackColorId = tv.b.ui.getColorIdForReservedName('black');
+tr.exportTo('tr.c', function() {
+  var elidedTitleCache = new tr.c.ElidedTitleCache();
+  var palette = tr.b.ui.getColorPalette();
+  var EventPresenter = tr.c.EventPresenter;
+  var blackColorId = tr.b.ui.getColorIdForReservedName('black');
 
   /**
    * This value is used to allow for consistent style UI elements.
@@ -157,11 +157,11 @@
     ctx.save();
     dt.applyTransformToCanvas(ctx);
 
-    var tr = new tv.c.FastRectRenderer(
+    var rect = new tr.c.FastRectRenderer(
         ctx, 2 * pixWidth, 2 * pixWidth, palette);
-    tr.setYandH(0, height);
+    rect.setYandH(0, height);
 
-    var lowSlice = tv.b.findLowIndexInSortedArray(
+    var lowSlice = tr.b.findLowIndexInSortedArray(
         slices,
         function(slice) { return slice.start + slice.duration; },
         viewLWorld);
@@ -186,17 +186,17 @@
       var lightAlpha = alpha * 0.70;
 
       if (slice.isTopLevel) {
-        tr.setYandH(3, height - 3);
+        rect.setYandH(3, height - 3);
         hadTopLevel = true;
       } else {
-        tr.setYandH(0, height);
+        rect.setYandH(0, height);
       }
 
       // If cpuDuration is available, draw rectangles proportional to the
       // amount of cpu time taken.
       if (!slice.cpuDuration) {
         // No cpuDuration available, draw using only one alpha.
-        tr.fillRect(x, w, colorId, alpha);
+        rect.fillRect(x, w, colorId, alpha);
         continue;
       }
 
@@ -224,7 +224,7 @@
       //
       // First draw the solid color, representing the 'active' part.
       if (activeWidth > 0) {
-        tr.fillRect(x, activeWidth, colorId, alpha);
+        rect.fillRect(x, activeWidth, colorId, alpha);
       }
 
       // Next draw the two toned 'idle' part.
@@ -233,24 +233,24 @@
       // ('active' and 'idle') may appear split apart.
       if (waitingWidth > 0) {
         // First draw the light toned top part.
-        tr.setYandH(0, lightRectHeight);
-        tr.fillRect(x + activeWidth - pixWidth,
+        rect.setYandH(0, lightRectHeight);
+        rect.fillRect(x + activeWidth - pixWidth,
             waitingWidth + pixWidth, colorId, lightAlpha);
         // Then the solid bottom half.
-        tr.setYandH(lightRectHeight, darkRectHeight);
-        tr.fillRect(x + activeWidth - pixWidth,
+        rect.setYandH(lightRectHeight, darkRectHeight);
+        rect.fillRect(x + activeWidth - pixWidth,
             waitingWidth + pixWidth, colorId, alpha);
         // Reset for the next slice.
-        tr.setYandH(0, height);
+        rect.setYandH(0, height);
       }
     }
-    tr.flush();
+    rect.flush();
 
     if (async && hadTopLevel) {
       // Draw a top border over async slices in order to visually separate
       // them from events above it.
       // See https://github.com/google/trace-viewer/issues/725.
-      tr.setYandH(2, 1);
+      rect.setYandH(2, 1);
       for (var i = lowSlice; i < slices.length; ++i) {
         var slice = slices[i];
         var x = slice.start;
@@ -267,9 +267,9 @@
             w = pixWidth;
         }
 
-        tr.fillRect(x, w, blackColorId, 0.7);
+        rect.fillRect(x, w, blackColorId, 0.7);
       }
-      tr.flush();
+      rect.flush();
     }
 
     ctx.restore();
@@ -305,7 +305,7 @@
     dt.applyTransformToCanvas(ctx);
     ctx.beginPath();
 
-    var lowSlice = tv.b.findLowIndexInSortedArray(
+    var lowSlice = tr.b.findLowIndexInSortedArray(
         slices,
         function(slice) { return slice.start; },
         viewLWorld);
@@ -360,7 +360,7 @@
 
     var cY = yOffset * pixelRatio;
 
-    var lowSlice = tv.b.findLowIndexInSortedArray(
+    var lowSlice = tr.b.findLowIndexInSortedArray(
         slices,
         function(slice) { return slice.start + slice.duration; },
         viewLWorld);
diff --git a/trace-viewer/trace_viewer/core/elided_cache.html b/trace-viewer/trace_viewer/core/elided_cache.html
index ec9cf6f..1971aff 100644
--- a/trace-viewer/trace_viewer/core/elided_cache.html
+++ b/trace-viewer/trace_viewer/core/elided_cache.html
@@ -11,7 +11,7 @@
 /**
  * @fileoverview Provides a caching layer for elided text values.
  */
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   /**
    * Cache for elided strings.
    * Moved from the ElidedTitleCache protoype to a "global" for speed
diff --git a/trace-viewer/trace_viewer/core/event_presenter.html b/trace-viewer/trace_viewer/core/event_presenter.html
index f0ef362..4d0fdea 100644
--- a/trace-viewer/trace_viewer/core/event_presenter.html
+++ b/trace-viewer/trace_viewer/core/event_presenter.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/selection_state.html">
 <link rel="import" href="/base/ui/color_scheme.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
@@ -14,11 +14,11 @@
 /**
  * @fileoverview Provides color scheme related functions.
  */
-tv.exportTo('tv.c', function() {
-  var paletteRaw = tv.b.ui.getRawColorPalette();
-  var palette = tv.b.ui.getColorPalette();
+tr.exportTo('tr.c', function() {
+  var paletteRaw = tr.b.ui.getRawColorPalette();
+  var palette = tr.b.ui.getColorPalette();
 
-  var SelectionState = tv.c.trace_model.SelectionState;
+  var SelectionState = tr.model.SelectionState;
 
   /**
    * Provides methods to get view values for events.
@@ -31,9 +31,9 @@
 
     getColorIdOffset_: function(event) {
       if (event.selectionState === SelectionState.SELECTED)
-        return tv.b.ui.paletteProperties.highlightIdBoost;
+        return tr.b.ui.paletteProperties.highlightIdBoost;
       else if (event.selectionState === SelectionState.DIMMED)
-        return tv.b.ui.paletteProperties.desaturateIdBoost;
+        return tr.b.ui.paletteProperties.desaturateIdBoost;
       return 0;
     },
 
@@ -56,12 +56,12 @@
 
     getInstantSliceColor: function(instant) {
       var colorId = instant.colorId + this.getColorIdOffset_(instant);
-      return tv.b.ui.colorToRGBAString(paletteRaw[colorId], 1.0);
+      return tr.b.ui.colorToRGBAString(paletteRaw[colorId], 1.0);
     },
 
     getObjectInstanceColor: function(instance) {
       var colorId = instance.colorId + this.getColorIdOffset_(instance);
-      return tv.b.ui.colorToRGBAString(paletteRaw[colorId], 0.25);
+      return tr.b.ui.colorToRGBAString(paletteRaw[colorId], 0.25);
     },
 
     getObjectSnapshotColor: function(snapshot) {
@@ -73,7 +73,7 @@
     getCounterSeriesColor: function(colorId, selectionState,
                                     opt_alphaMultiplier) {
       var event = {selectionState: selectionState};
-      return tv.b.ui.colorToRGBAString(
+      return tr.b.ui.colorToRGBAString(
           paletteRaw[colorId + this.getColorIdOffset_(event)],
               (opt_alphaMultiplier !== undefined ? opt_alphaMultiplier : 1.0));
     },
@@ -81,9 +81,9 @@
     getBarSnapshotColor: function(snapshot, offset) {
       var colorId =
           (snapshot.objectInstance.colorId + offset) %
-          tv.b.ui.paletteProperties.numGeneralPurposeColorIds;
+          tr.b.ui.paletteProperties.numGeneralPurposeColorIds;
       colorId += this.getColorIdOffset_(snapshot);
-      return tv.b.ui.colorToRGBAString(paletteRaw[colorId], 1.0);
+      return tr.b.ui.colorToRGBAString(paletteRaw[colorId], 1.0);
     }
   };
 
diff --git a/trace-viewer/trace_viewer/core/fast_rect_renderer.html b/trace-viewer/trace_viewer/core/fast_rect_renderer.html
index 568bb40..9a73353 100644
--- a/trace-viewer/trace_viewer/core/fast_rect_renderer.html
+++ b/trace-viewer/trace_viewer/core/fast_rect_renderer.html
@@ -31,7 +31,7 @@
  * Make sure to flush the trackRenderer before finishing drawing in order
  * to commit any queued drawing operations.
  */
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
 
   /**
    * Creates a fast rect renderer with a specific set of culling rules
diff --git a/trace-viewer/trace_viewer/core/favicons.html b/trace-viewer/trace_viewer/core/favicons.html
index d72d165..b48a727 100644
--- a/trace-viewer/trace_viewer/core/favicons.html
+++ b/trace-viewer/trace_viewer/core/favicons.html
@@ -7,7 +7,7 @@
 <link rel="import" href="/base/base.html">
 <script>
 'use strict';
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   var FaviconsByHue = {
     blue: 'data:image/vndmicrosofticon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjj8xAGArIgqOPzE8nUY3dqJJOJeiSTiXnUY3do4/MTxhKyIKjkAxAAAAAAAAAAAAAAAAAAAAAABQJBwAAAAAAZJBMzSoSzqlsU8+6bRQP/21UT//tVE//7RQP/2wTz3ppko6pY9AMjQAAAABTyMbAAAAAAB7e3sAAP//AKFSRE+wTz3dtVE//7VRP/+1UT//tVE//7VRP/+zUD7/sE89/7BOPf+qTDvdl0M0TwAAAABWJx4A+fn5ANjd3TnIiX7ftVA9/7VRP/+1UT//tVE//7VRP/+xTz3/rE08/6xMO/+sTDv/rE08/6dKOt+SQTM5q0w7ALO0tA3v8fGu05uR/7NMOf+0Tzz/tE88/7RPPv+uTT3/p0o7/6ZJOv+mSTr/pkk6/6ZJOv+mSjr/n0Y4rnIwKg3h4eFK9/j48N2zrP/FeGr/xnps/8Z6bP/AaUv/tlw1/7RbNf+1WzX/tFs1/7RbNf+0WzX/tFs1/7NbNPCqWy1K7e3tjPn5+f/49vX/9vLy//by8v/28vH/8bZv/+6RH//ukyP/7pMj/+6SI//ukiP/7pMj/+2SIv/qjyL/34kfjPHx8bL5+fn/+fn5//n5+f/5+fr/+fn5//W7cP/zlB3/85Yh//OWIf/zliH/85Yh//GVIf/rkR//6ZAf/+KLHrLz8/O2+fn5//n5+f/5+fn/+fn5//n5+f/1unD/85Qd//OWIf/zliH/85Yh//CUIP/mjh//44we/+OMHv/diR628vLymfn5+f/5+fn/+fn5//n5+f/5+fn/9bx0//OXI//zmCb/85gm/++VIv/hjB//3Yoe/92KHv/dih7/2IYdmfHx8Vz4+Pj3+fn5//n5+f/5+fn/+fn5//jo0//33bv/9929//bbtf/euDX/06oJ/9OrC//Tqwv/06oM98yfD1zr6+sY9/f3xvn5+f/5+fn/+fn5//n5+f/5+vv/+fv8//n7/f/3+PH/3Ms6/9O8AP/UvQD/1L0A/9K8AMbItAAY////APT09Fb4+Pjy+fn5//n5+f/5+fn/+fn5//n5+f/5+fr/9/bu/9zKOf/TuwD/1LwA/9S8APLQuABW3cQAAOzs7ADm5uYF9vb2ePn5+fT5+fn/+fn5//n5+f/5+fn/+fn6//f27v/cyTn/07sA/9S8APTRugB4w60ABcmyAAAAAAAA8PDwAOzs7Ab29vZd+Pj40vn5+fz5+fn/+fn5//n5+f/49/H/5Ndu/NjEIdLSugBdybIABsy1AAAAAAAAAAAAAAAAAADn5+cAqKioAPT09CH39/dy+Pj4tvj4+NX4+PjV+Pj4tvX063Lt6MMhOQAAAM+/RAAAAAAAAAAAAPAPAADAAwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAASCwAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCwUEDDgZExxWJx4tYiwiN2IsIjdWJx4tOBkTHAsFBAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAbDAkKZS0jMYs+MWydRjeipko6x6tMO9utTTzjrU0846tMO9umSjrHnUY3oos+MWxlLSMxGwwJCv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgZFAAPBwUHcjMoPJtFNpqsTTzhs1A+/LVRP/+2UT//tVE//7VRP/+1UT//tVE//7ZRP/+1UT//s1A+/KxNPOGbRTaacTInPA8HBQc4GRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/yp4AUCQcGZVDNICtTjzktVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+0UT//s1A+/7JQPv+rTDvkkkEzgE8jGxn/xZoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA////AGswJSqiSTivs1A++7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tFA+/7FPPf+xTz3/sU89/7FPPf+vTj37nkc3r2guJCr///8AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAP/DogB/VEwsqE09v7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7NQPv+vTj3/r049/69OPf+vTj3/r049/69OPf+uTjz/oUg4v20xJiz/nnsAAgEBAAAAAAAAAAAAAAAAAAAAAAD19fUAkp2fHdK2sbW5W0r/tVA+/7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+yUD7/rU08/6xNPP+tTTz/rU08/61NPP+tTTz/rU08/61NPP+sTTz/nkY3tWAqIR2pSzsAAAAAAAAAAAAAAAAAeXl5ADY2Ngnd39+O6tbT/blbSv+1UD7/tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//slA+/6xNPP+rTDv/q0w7/6tMO/+rTDv/q0w7/6tMO/+rTDv/q0w7/6tMO/+qTDv9lkM0jiUQDQlSJR0AAAAAAAAAAAD///8AxMTES/X29u3s2NX/uVtK/7VQPv+1UT//tVE//7VRP/+1UT//tVE//7VRP/+1UT//tVE//7FPPv+qTDv/qEs6/6hLOv+oSzr/qEs6/6hLOv+oSzr/qEs6/6hLOv+oSzr/qEs6/6lLOv+lSTnthDsuS/+TcgAAAAAAm5ubAHBwcA/o6Oix+vv8/+zY1P+5W0r/tVA+/7VRP/+1UT//tVE//7VRP/+1UT//tVE//7VRP/+xTz3/qEs6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+mSjr/pko6/6ZKOv+bRTaxSiEaD2cuJAD///8AycnJRfX19fD6+/z/69fU/7hYR/+0Tjv/tE48/7ROPP+0Tjz/tE48/7ROPP+0Tz3/r04+/6VJOv+jSDn/o0g5/6NIOf+jSDn/o0g5/6NIOf+jSDn/o0g5/6NIOf+jSDr/o0g5/6NIOf+jSDn/o0g6/6BHOfCCOS9F0FxKAAAAAALk5OSN+fn5//n6+v/y5+X/05uS/9CTiP/QlIn/0JSJ/9CUif/QlIn/0JSK/8yGb//AaDb/vWc0/71nNf+9ZzT/vWc0/71nNP+9ZjT/vWY0/71mNP+9ZjT/vGY0/7xmNP+8ZjT/vGY0/7xmNP+8ZjT/u2U0/7FiLY0AAAACk5OTFu/v78X5+fn/+fn5//n5+f/5+vr/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//KWI//ylSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//GVIf/xlSH/8ZUh//CUIf/vkyD/5Y0fxY1XExbDw8Mz9PT05fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LL/85cj//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/wlCD/7pIg/+6SIP/pjx/lunIZM9XV1VD39/f0+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fv9//fYsv/zlyP/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/75Mg/+uRH//qkB//6pAf/+iPH/TIfBtQ3d3dYfj4+Pn5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//OXI//zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh/+6TIP/ojx//548f/+ePH//njx//5o4f+c1/HGHh4eFl+Pj4+vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LL/85cj//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/tkiD/5Y0f/+SNH//ljR//5Y0f/+WNH//kjB/6zn8cZeDg4Fr4+Pj3+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fv9//fYsv/zlyP/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/65Eg/+KMHv/iix7/4ose/+KLHv/iix7/4ose/+CLHvfLfRta3NzcQvf39+/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+/3/99iy//OXI//zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh/+qRIP/gih7/34oe/9+KHv/fih7/34oe/9+KHv/fih7/3Yge78V6GkLS0tIj9fX12fn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n7/f/32LH/85Yg//OVHv/zlR7/85Ue//OVHv/zlR7/85Ue//OVIf/pjyH/3ogf/92HH//dhx//3Ycf/92HH//dhx//3Ycf/92HH//ahh7ZunMZI56engjy8vKu+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fr7//jr2f/2ypL/9smP//bJkP/2yZD/9smQ//bJkP/2yZD/5rNI/9OeFP/SnhX/0p4V/9KeFf/SnhX/0Z0V/9GdFf/RnRX/0Z0V/8yWFq6KVBcI////AO3t7Wr5+fn++fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn6//n6/P/5+vz/+fr8//n6/P/5+vz/+fr8//n6/P/h013/0rsA/9O8AP/TvAD/07wA/9O8AP/TvAD/07wA/9O8AP/SvAD+yLMAav/mAADr6+sA4eHhJPb29tv5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+LSW//TuwD/1LwA/9S8AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9K6ANu/qgAkyLEAALu7uwAAAAAA8vLygfn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/4tJb/9O7AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9S8AP/UvAD/zrYAgQAAAACfjQAAAAAAAOzs7ADk5OQe9vb2zPn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i0lv/07sA/9S8AP/UvAD/1LwA/9S8AP/UvAD/1LwA/9K6AMzCrAAeybIAAAAAAAAAAAAAsLCwAP///wDv7+9O+Pj47Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+LSW//TuwD/1LwA/9S8AP/UvAD/1LwA/9S8AP/TuwDsy7QATu7UAACXhQAAAAAAAAAAAAAAAAAA1tbWALS0tAPy8vJv+Pj49Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/4tJb/9O7AP/UvAD/1LwA/9S8AP/UvAD/07wA9M63AG6ZiQADtqIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4uLiANfX1wbz8/Nz+Pj48Pn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/i0lv/07sA/9S8AP/UvAD/1LwA/9O8APDPuABzuKMABsGrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+PjANjY2ATy8vJZ+Pj42vn5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5/+HSW//TugD/1LsA/9S8AP/TuwDazrcAWbejAATBqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1NTUAB8fHwDw8PAr9vb2nPj4+O35+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/7uas/+bZdv/j1mvt2cYznMu0ACsUFAAAtaEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOvr6wDj4+MG8vLyOvb29pD4+PjS+fn58vn5+f35+fn/+fn5//n5+f/5+fn/+fn5/fn5+fL4+frS9/j8kPT1/Trs8v8G8PP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh4eEA1tbWAu/v7xv09PRJ9vb2dvb29pf39/eo9/f3qPb29pf29vZ29PT0Se/v7xvW1tYC4eHhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABwAAAA8AAAAPgAAAH4AAAB/AAAA/4AAAf/gAAf/8AAP//wAP/', // @suppress longLineCheck
 
@@ -22,4 +22,4 @@
     FaviconsByHue: FaviconsByHue
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/core/filter.html b/trace-viewer/trace_viewer/core/filter.html
index f94b7f4..698146a 100644
--- a/trace-viewer/trace_viewer/core/filter.html
+++ b/trace-viewer/trace_viewer/core/filter.html
@@ -8,13 +8,13 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   function matchLower(value, pattern) {
     return value.toLowerCase().indexOf(pattern) !== -1;
   }
 
   /**
-   * @constructor The generic base class for filtering a TraceModel based on
+   * @constructor The generic base class for filtering a Model based on
    * various rules. The base class returns true for everything.
    */
   function Filter() { }
diff --git a/trace-viewer/trace_viewer/core/filter_test.html b/trace-viewer/trace_viewer/core/filter_test.html
index be0e310..72cb057 100644
--- a/trace-viewer/trace_viewer/core/filter_test.html
+++ b/trace-viewer/trace_viewer/core/filter_test.html
@@ -12,9 +12,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TitleOrCategoryFilter = tv.c.TitleOrCategoryFilter;
-  var ExactTitleFilter = tv.c.ExactTitleFilter;
+tr.b.unittest.testSuite(function() {
+  var TitleOrCategoryFilter = tr.c.TitleOrCategoryFilter;
+  var ExactTitleFilter = tr.c.ExactTitleFilter;
 
   test('titleOrCategoryFilter', function() {
     assert.throw(function() {
@@ -24,14 +24,14 @@
       new TitleOrCategoryFilter('');
     });
 
-    var s0 = tv.c.test_utils.newSliceCategory('cat', 'a', 1, 3);
+    var s0 = tr.c.test_utils.newSliceCategory('cat', 'a', 1, 3);
     assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s0));
     assert.isTrue(new TitleOrCategoryFilter('cat').matchSlice(s0));
     assert.isTrue(new TitleOrCategoryFilter('at').matchSlice(s0));
     assert.isFalse(new TitleOrCategoryFilter('b').matchSlice(s0));
     assert.isFalse(new TitleOrCategoryFilter('X').matchSlice(s0));
 
-    var s1 = tv.c.test_utils.newSliceCategory('cat', 'abc', 1, 3);
+    var s1 = tr.c.test_utils.newSliceCategory('cat', 'abc', 1, 3);
     assert.isTrue(new TitleOrCategoryFilter('abc').matchSlice(s1));
     assert.isTrue(new TitleOrCategoryFilter('Abc').matchSlice(s1));
     assert.isTrue(new TitleOrCategoryFilter('cat').matchSlice(s1));
@@ -48,12 +48,12 @@
       new ExactTitleFilter('');
     });
 
-    var s0 = tv.c.test_utils.newSliceNamed('a', 1, 3);
+    var s0 = tr.c.test_utils.newSliceNamed('a', 1, 3);
     assert.isTrue(new ExactTitleFilter('a').matchSlice(s0));
     assert.isFalse(new ExactTitleFilter('b').matchSlice(s0));
     assert.isFalse(new ExactTitleFilter('A').matchSlice(s0));
 
-    var s1 = tv.c.test_utils.newSliceNamed('abc', 1, 3);
+    var s1 = tr.c.test_utils.newSliceNamed('abc', 1, 3);
     assert.isTrue(new ExactTitleFilter('abc').matchSlice(s1));
     assert.isFalse(new ExactTitleFilter('Abc').matchSlice(s1));
     assert.isFalse(new ExactTitleFilter('bc').matchSlice(s1));
diff --git a/trace-viewer/trace_viewer/core/find_control.html b/trace-viewer/trace_viewer/core/find_control.html
index 441d824..84c1e3a 100644
--- a/trace-viewer/trace_viewer/core/find_control.html
+++ b/trace-viewer/trace_viewer/core/find_control.html
@@ -116,7 +116,6 @@
     },
 
     filterFocus: function(e) {
-      this.controller.reset();
       this.$.filter.select();
     },
 
@@ -144,10 +143,9 @@
     },
 
     filterTextChanged: function() {
-      this.controller.filterText = this.$.filter.value;
       this.$.hitCount.textContent = '';
       this.$.spinner.style.visibility = 'visible';
-      this.controller.updateFilterHits().then(function() {
+      this.controller.startFiltering(this.$.filter.value).then(function() {
         this.$.spinner.style.visibility = 'hidden';
         this.updateHitCountEl();
       }.bind(this));
diff --git a/trace-viewer/trace_viewer/core/find_control_test.html b/trace-viewer/trace_viewer/core/find_control_test.html
index 2e4fd5c..e21ed9f 100644
--- a/trace-viewer/trace_viewer/core/find_control_test.html
+++ b/trace-viewer/trace_viewer/core/find_control_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
     var ctl = new TracingFindControl();
     ctl.controller = {
diff --git a/trace-viewer/trace_viewer/core/find_controller.html b/trace-viewer/trace_viewer/core/find_controller.html
index 1d5ddae..637c8aa 100644
--- a/trace-viewer/trace_viewer/core/find_controller.html
+++ b/trace-viewer/trace_viewer/core/find_controller.html
@@ -15,15 +15,15 @@
 /**
  * @fileoverview FindController.
  */
-tv.exportTo('tv.c', function() {
-  var Task = tv.b.Task;
+tr.exportTo('tr.c', function() {
+  var Task = tr.b.Task;
 
   function FindController(selectionController) {
     this.selectionController_ = selectionController;
-    this.filterText_ = '';
-    this.filterHits_ = new tv.c.Selection();
-    this.filterHitsDirty_ = true;
+    this.filterHits_ = new tr.c.Selection();
     this.currentHitIndex_ = -1;
+    this.activePromise_ = Promise.resolve();
+    this.activeTask_ = undefined;
   };
 
   FindController.prototype = {
@@ -37,54 +37,40 @@
       return this.selectionController_;
     },
 
-    get filterText() {
-      return this.filterText_;
-    },
-
-    set filterText(f) {
-      if (f == this.filterText_)
-        return;
-      this.filterText_ = f;
-      this.filterHitsDirty_ = true;
-    },
-
-    getFilterPromise_: function(filterText) {
-      if (!this.selectionController_)
-        return;
-      var promise = Promise.resolve();
-
-
-      var sc = this.selectionController_;
-
-      var filter = new tv.c.TitleOrCategoryFilter(filterText);
-      var filterHits = new tv.c.Selection();
-      var filterTask = sc.addAllEventsMatchingFilterToSelectionAsTask(
-          filter, filterHits);
-      promise = Task.RunWhenIdle(filterTask);
-      promise.then(function() {
-        this.filterHitsDirty_ = false;
-        this.filterHits_ = filterHits;
-        sc.findTextChangedTo(filterHits);
-      }.bind(this));
-      return promise;
-    },
-
-    clearFindSelections_: function() {
-      this.selectionController_.findTextCleared();
+    enqueueOperation_: function(operation) {
+      var task;
+      if (operation instanceof tr.b.Task)
+        task = operation;
+      else
+        task = new tr.b.Task(operation, this);
+      if (this.activeTask_) {
+        this.activeTask_ = this.activeTask_.enqueue(task);
+      } else {
+        // We're enqueuing the first task, schedule it.
+        this.activeTask_ = task;
+        this.activePromise_ = Task.RunWhenIdle(this.activeTask_);
+        this.activePromise_.then(function() {
+          this.activePromise_ = undefined;
+          this.activeTask_ = undefined;
+        }.bind(this));
+      }
     },
 
     /**
-     * Updates the filter hits based on the current filtering settings. Returns
-     * a promise which resolves when |filterHits| has been refreshed.
+     * Updates the filter hits based on the provided |filterText|. Returns a
+     * promise which resolves when |filterHits| has been refreshed.
      */
-    updateFilterHits: function() {
-      var promise = Promise.resolve();
+    startFiltering: function(filterText) {
+      var sc = this.selectionController_;
+      if (!sc)
+        return;
 
-      if (!this.filterHitsDirty_)
-        return promise;
-
-      this.filterHits_ = new tv.c.Selection();
-      this.currentHitIndex_ = -1;
+      // TODO(beaudoin): Cancel anything left in the task queue, without
+      // invalidating the promise.
+      this.enqueueOperation_(function() {
+        this.filterHits_ = new tr.c.Selection();
+        this.currentHitIndex_ = -1;
+      }.bind(this));
 
       // Try constructing a UIState from the filterText.
       // UIState.fromUserFriendlyString will throw an error only if the string
@@ -92,32 +78,42 @@
       // It will return undefined if there is no syntactic match.
       var stateFromString;
       try {
-        stateFromString = this.selectionController_.uiStateFromString(
-            this.filterText);
+        stateFromString = sc.uiStateFromString(filterText);
       } catch (e) {
-        var overlay = new tv.b.ui.Overlay();
-        overlay.textContent = e.message;
-        overlay.title = 'UI State Navigation Error';
-        overlay.visible = true;
-        return promise;
+        this.enqueueOperation_(function() {
+          var overlay = new tr.b.ui.Overlay();
+          overlay.textContent = e.message;
+          overlay.title = 'UI State Navigation Error';
+          overlay.visible = true;
+        });
+        return this.activePromise_;
       }
 
       if (stateFromString !== undefined) {
-        this.selectionController_.navToPosition(stateFromString, true);
+        this.enqueueOperation_(
+            sc.navToPosition.bind(this, stateFromString, true));
       } else {
         // filterText is not a navString here -- proceed with find and filter.
-        if (this.filterText.length === 0)
-          this.clearFindSelections_();
-        else
-          promise = this.getFilterPromise_(this.filterText);
+        if (filterText.length === 0) {
+          this.enqueueOperation_(sc.findTextCleared.bind(sc));
+        } else {
+          var filter = new tr.c.TitleOrCategoryFilter(filterText);
+          var filterHits = new tr.c.Selection();
+          this.enqueueOperation_(sc.addAllEventsMatchingFilterToSelectionAsTask(
+              filter, filterHits));
+          this.enqueueOperation_(function() {
+            this.filterHits_ = filterHits;
+            sc.findTextChangedTo(filterHits);
+          }.bind(this));
+        }
       }
-      return promise;
+      return this.activePromise_;
     },
 
     /**
-     * Returns the most recent filter hits as a tv.c.Selection. Call
-     * |updateFilterHits| to ensure this is up to date after the filter
-     * settings have been changed.
+     * Returns the most recent filter hits as a tr.c.Selection. Call
+     * |startFiltering| to ensure this is up to date after the filter settings
+     * have been changed.
      */
     get filterHits() {
       return this.filterHits_;
@@ -148,11 +144,6 @@
 
     findPrevious: function() {
       this.find_(-1);
-    },
-
-    reset: function() {
-      this.filterText_ = '';
-      this.filterHitsDirty_ = true;
     }
   };
 
diff --git a/trace-viewer/trace_viewer/core/find_controller_test.html b/trace-viewer/trace_viewer/core/find_controller_test.html
index b319fa4..379d5fe 100644
--- a/trace-viewer/trace_viewer/core/find_controller_test.html
+++ b/trace-viewer/trace_viewer/core/find_controller_test.html
@@ -14,8 +14,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Task = tv.b.Task;
+tr.b.unittest.testSuite(function() {
+  var Task = tr.b.Task;
 
   /*
    * Just enough of the SelectionController to support the tests below.
@@ -25,8 +25,8 @@
 
     this.viewport = undefined;
     this.model = undefined;
-    this.selection = new tv.c.Selection();
-    this.findMatches = new tv.c.Selection();
+    this.selection = new tr.c.Selection();
+    this.findMatches = new tr.c.Selection();
   }
 
   FakeSelectionController.prototype = {
@@ -46,7 +46,7 @@
 
     findTextChangedTo: function(selection) {
       this.findMatches = selection;
-      this.selection = new tv.c.Selection();
+      this.selection = new tr.c.Selection();
     },
 
     findFocusChangedTo: function(selection) {
@@ -54,8 +54,8 @@
     },
 
     findTextCleared: function(selection) {
-      this.selection = new tv.c.Selection();
-      this.findMatches = new tv.c.Selection();
+      this.selection = new tr.c.Selection();
+      this.findMatches = new tr.c.Selection();
     }
   };
 
@@ -70,22 +70,22 @@
     }
 
     var message = opt_message || 'Expected array ' + a + ', got array ' + b;
-    throw new tv.b.unittest.TestError(message);
+    throw new tr.b.unittest.TestError(message);
   };
 
   test('findControllerNoModel', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.FindController(selectionController);
+    var controller = new tr.c.FindController(selectionController);
     controller.findNext();
     controller.findPrevious();
   });
 
   test('findControllerEmptyHit', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.FindController(selectionController);
+    var controller = new tr.c.FindController(selectionController);
 
-    selectionController.selection = new tv.c.Selection();
-    selectionController.findMatches = new tv.c.Selection();
+    selectionController.selection = new tr.c.Selection();
+    selectionController.findMatches = new tr.c.Selection();
     controller.findNext();
     assertArrayShallowEquals([], selectionController.selection);
     assertArrayShallowEquals([], selectionController.findMatches);
@@ -96,14 +96,13 @@
 
   test('findControllerOneHit', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.FindController(selectionController);
+    var controller = new tr.c.FindController(selectionController);
 
     var s1 = {guid: 1};
     selectionController.addAllEventsMatchingFilterToSelectionReturnValue = [
       s1
     ];
-    controller.filterText = 'asdf';
-    var promise = controller.updateFilterHits();
+    var promise = controller.startFiltering('asdf');
     promise.then(function() {
       assertArrayShallowEquals([], selectionController.selection);
       assertArrayShallowEquals([s1], selectionController.findMatches);
@@ -122,7 +121,7 @@
 
   test('findControllerMultipleHits', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.FindController(selectionController);
+    var controller = new tr.c.FindController(selectionController);
 
     var s1 = {guid: 1};
     var s2 = {guid: 2};
@@ -131,8 +130,7 @@
     selectionController.addAllEventsMatchingFilterToSelectionReturnValue = [
       s1, s2, s3
     ];
-    controller.filterText = 'asdf';
-    var promise = controller.updateFilterHits();
+    var promise = controller.startFiltering('asdf');
     promise.then(function() {
       // Loop through hits then when we wrap, try moving backward.
       assertArrayShallowEquals([], selectionController.selection);
@@ -156,7 +154,7 @@
 
   test('findControllerChangeFilterAfterNext', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.FindController(selectionController);
+    var controller = new tr.c.FindController(selectionController);
 
     var s1 = {guid: 1};
     var s2 = {guid: 2};
@@ -166,8 +164,7 @@
     selectionController.addAllEventsMatchingFilterToSelectionReturnValue = [
       s1, s2, s3
     ];
-    controller.filterText = 'asdf';
-    var promise = controller.updateFilterHits();
+    var promise = controller.startFiltering('asdf');
     promise.then(function() {
       // Loop through hits then when we wrap, try moving backward.
       controller.findNext();
@@ -175,8 +172,7 @@
         s4
       ];
 
-      controller.filterText = 'asdfsf';
-      var nextPromise = controller.updateFilterHits();
+      var nextPromise = controller.startFiltering('asdfsf');
       nextPromise.then(function() {
         controller.findNext();
         assertArrayShallowEquals([s4], selectionController.selection);
@@ -187,7 +183,7 @@
 
   test('findControllerSelectsAllItemsFirst', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.FindController(selectionController);
+    var controller = new tr.c.FindController(selectionController);
 
     var s1 = {guid: 1};
     var s2 = {guid: 2};
@@ -195,8 +191,7 @@
     selectionController.addAllEventsMatchingFilterToSelectionReturnValue = [
       s1, s2, s3
     ];
-    controller.filterText = 'asdfsf';
-    var promise = controller.updateFilterHits();
+    var promise = controller.startFiltering('asdfsf');
     promise.then(function() {
       assertArrayShallowEquals([], selectionController.selection);
       assertArrayShallowEquals([s1, s2, s3], selectionController.findMatches);
@@ -210,15 +205,15 @@
   });
 
   test('findControllerWithRealTimeline', function() {
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       var p1 = model.getOrCreateProcess(1);
       var t1 = p1.getOrCreateThread(1);
-      t1.sliceGroup.pushSlice(new tv.c.trace_model.ThreadSlice(
+      t1.sliceGroup.pushSlice(new tr.model.ThreadSlice(
           '', 'a', 0, 1, {}, 3));
       model.t1 = t1;
     });
 
-    var timeline = new tv.c.TimelineView();
+    var timeline = new tr.c.TimelineView();
     timeline.model = model;
 
     var selectionController = timeline.selectionController;
@@ -228,11 +223,10 @@
     controller.findNext();
 
     // Test find with filter txt.
-    controller.filterText = 'a';
-    var promise = controller.updateFilterHits();
+    var promise = controller.startFiltering('a');
     promise = promise.then(function() {
       assert.equal(selectionController.selection.length, 0);
-      assert.deepEqual(tv.b.asArray(selectionController.findMatches),
+      assert.deepEqual(tr.b.asArray(selectionController.findMatches),
                        model.t1.sliceGroup.slices);
 
       controller.findNext();
@@ -240,8 +234,7 @@
       assert.equal(selectionController.selection[0],
                    model.t1.sliceGroup.slices[0]);
 
-      controller.filterText = 'xxx';
-      var nextPromise = controller.updateFilterHits();
+      var nextPromise = controller.startFiltering('xxx');
       nextPromise.then(function() {
         assert.equal(selectionController.findMatches.length, 0);
         assert.equal(selectionController.selection.length, 1);
@@ -257,9 +250,10 @@
 
   test('findControllerNavigation', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.FindController(selectionController);
+    var controller = new tr.c.FindController(selectionController);
 
     var navToPositionCallCount = 0;
+    var findTextClearedCallCount = 0;
     var fakeUIState = {};
     selectionController.uiStateFromString = function(string) {
       if (string === '')
@@ -271,18 +265,32 @@
       assert.equal(uiState, fakeUIState);
       navToPositionCallCount++;
     };
-
-    controller.filterText = '2000@1.2x7';
-    controller.updateFilterHits();
-    assert.equal(navToPositionCallCount, 1);
-
-    var findTextClearedCallCount = 0;
     selectionController.findTextCleared = function() {
       findTextClearedCallCount++;
     };
-    controller.filterText = '';
-    controller.updateFilterHits();
-    assert.equal(findTextClearedCallCount, 1);
+
+    var promise = controller.startFiltering('2000@1.2x7').then(function() {
+      assert.equal(navToPositionCallCount, 1);
+    });
+    promise = promise.then(controller.startFiltering.bind(controller, ''));
+    promise = promise.then(function() {
+      assert.equal(findTextClearedCallCount, 1);
+    });
+    return promise;
+  });
+
+  test('findControllerClearAfterSet', function() {
+    var selectionController = new FakeSelectionController();
+    var controller = new tr.c.FindController(selectionController);
+    var findTextChangedToCalled = false;
+    selectionController.findTextChangedTo = function(selection) {
+      findTextChangedToCalled = true;
+    };
+    selectionController.findTextCleared = function() {
+      assert.equal(findTextChangedToCalled, true);
+    };
+    controller.startFiltering('1');
+    controller.startFiltering('');
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/location.html b/trace-viewer/trace_viewer/core/location.html
index da91d23..75f9cc9 100644
--- a/trace-viewer/trace_viewer/core/location.html
+++ b/trace-viewer/trace_viewer/core/location.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   /**
    * YComponent is a class that handles storing the stableId and the percentage
    * offset in the y direction of all tracks within a specific viewX and viewY
@@ -59,7 +59,7 @@
           viewY + viewport.modelTrackContainer.canvas.offsetTop);
     // Build yComponents by calculating percentage offset with respect to
     // each parent track.
-    while (elem instanceof tv.c.tracks.Track) {
+    while (elem instanceof tr.c.tracks.Track) {
       if (elem.eventContainer) {
         var boundRect = elem.getBoundingClientRect();
         var yPercentOffset = (viewY - boundRect.top) / boundRect.height;
@@ -86,7 +86,7 @@
       return;
 
     var firstY = elem.getBoundingClientRect().top;
-    while (elem instanceof tv.c.tracks.Track) {
+    while (elem instanceof tr.c.tracks.Track) {
       if (elem.eventContainer) {
         var boundRect = elem.getBoundingClientRect();
         var yPercentOffset = (firstY - boundRect.top) / boundRect.height;
diff --git a/trace-viewer/trace_viewer/core/location_test.html b/trace-viewer/trace_viewer/core/location_test.html
index 6a90adb..8ef347f 100644
--- a/trace-viewer/trace_viewer/core/location_test.html
+++ b/trace-viewer/trace_viewer/core/location_test.html
@@ -9,29 +9,29 @@
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_track_view.html">
 <link rel="import" href="/core/timeline_viewport.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Location = tv.c.Location;
-  var Model = tv.c.TraceModel;
+tr.b.unittest.testSuite(function() {
+  var Location = tr.c.Location;
+  var Model = tr.Model;
 
   test('locationObj', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var process = model.getOrCreateProcess(123);
     var thread = process.getOrCreateThread(456);
 
     model.importTraces([], false, false, function() {
       thread.asyncSliceGroup.push(
-        tv.c.test_utils.newAsyncSliceNamed('a', 80, 20, thread, thread));
+        tr.c.test_utils.newAsyncSliceNamed('a', 80, 20, thread, thread));
       thread.asyncSliceGroup.push(
-        tv.c.test_utils.newAsyncSliceNamed('a', 85, 10, thread, thread));
+        tr.c.test_utils.newAsyncSliceNamed('a', 85, 10, thread, thread));
     });
 
-    var timeline = new tv.c.TimelineTrackView();
-    var vp = new tv.c.TimelineViewport(timeline);
+    var timeline = new tr.c.TimelineTrackView();
+    var vp = new tr.c.TimelineViewport(timeline);
     timeline.model = model;
     timeline.focusElement = timeline;
     timeline.tabIndex = 0;
@@ -51,7 +51,7 @@
       },
       addEventListener: function() {},
       canvas: {
-        offsetLeft: tv.c.constants.HEADING_WIDTH,
+        offsetLeft: tr.c.constants.HEADING_WIDTH,
         offsetTop: 0
       }
     };
diff --git a/trace-viewer/trace_viewer/core/scripting_control.html b/trace-viewer/trace_viewer/core/scripting_control.html
index 87dad08..87344eb 100644
--- a/trace-viewer/trace_viewer/core/scripting_control.html
+++ b/trace-viewer/trace_viewer/core/scripting_control.html
@@ -133,9 +133,9 @@
         result = e.stack || e.stackTrace;
       }
 
-      if (result instanceof tv.b.Task) {
+      if (result instanceof tr.b.Task) {
         // TODO(skyostil): Show a cool spinner.
-        tv.b.Task.RunWhenIdle(result);
+        tr.b.Task.RunWhenIdle(result);
       } else {
         this.addLine_(result);
       }
diff --git a/trace-viewer/trace_viewer/core/scripting_control_test.html b/trace-viewer/trace_viewer/core/scripting_control_test.html
index da94495..63ccf08 100644
--- a/trace-viewer/trace_viewer/core/scripting_control_test.html
+++ b/trace-viewer/trace_viewer/core/scripting_control_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
     var ctl = new TracingScriptingControl();
     this.addHTMLOutput(ctl);
diff --git a/trace-viewer/trace_viewer/core/scripting_controller.html b/trace-viewer/trace_viewer/core/scripting_controller.html
index b72d74d..8afc629 100644
--- a/trace-viewer/trace_viewer/core/scripting_controller.html
+++ b/trace-viewer/trace_viewer/core/scripting_controller.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   function ScriptingController(selectionController) {
     this.selectionController_ = selectionController;
     this.scriptObjectNames_ = [];
@@ -30,8 +30,8 @@
 
   function ScriptingObjectRegistry() {
   }
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
-  tv.b.decorateExtensionRegistry(ScriptingObjectRegistry, options);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+  tr.b.decorateExtensionRegistry(ScriptingObjectRegistry, options);
 
   ScriptingController.prototype = {
     get selectionController() {
diff --git a/trace-viewer/trace_viewer/core/scripting_controller_test.html b/trace-viewer/trace_viewer/core/scripting_controller_test.html
index 6603acc..d91f18d 100644
--- a/trace-viewer/trace_viewer/core/scripting_controller_test.html
+++ b/trace-viewer/trace_viewer/core/scripting_controller_test.html
@@ -13,31 +13,31 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function FakeSelectionController() {
-    tv.b.EventTarget.call(this);
+    tr.b.EventTarget.call(this);
 
     this.addAllEventsMatchingFilterToSelectionReturnValue = [];
 
     this.viewport = undefined;
     this.model = undefined;
-    this.selection = new tv.c.Selection();
-    this.highlight = new tv.c.Selection();
+    this.selection = new tr.c.Selection();
+    this.highlight = new tr.c.Selection();
   }
   FakeSelectionController.prototype = {
-    __proto__: tv.b.EventTarget.prototype
+    __proto__: tr.b.EventTarget.prototype
   };
 
   test('scriptingControllerBasicArithmetic', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.ScriptingController(selectionController);
+    var controller = new tr.c.ScriptingController(selectionController);
     var result = controller.executeCommand('1 + 1');
     assert.equal(result, 2);
   });
 
   test('scriptingControllerNonLocalContext', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.ScriptingController(selectionController);
+    var controller = new tr.c.ScriptingController(selectionController);
     var x = 1;
     controller.executeCommand('x = 2');
     assert.equal(x, 1);
@@ -45,7 +45,7 @@
 
   test('scriptingControllerModifyGlobalContext', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.ScriptingController(selectionController);
+    var controller = new tr.c.ScriptingController(selectionController);
     window._x = 1;
     controller.executeCommand('_x = 2');
     assert.equal(window._x, 2);
@@ -54,7 +54,7 @@
 
   test('scriptingControllerPersistentContext', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.ScriptingController(selectionController);
+    var controller = new tr.c.ScriptingController(selectionController);
     controller.executeCommand('a = 42');
     var result = controller.executeCommand('a');
     assert.equal(result, 42);
@@ -62,7 +62,7 @@
 
   test('scriptingControllerAddScriptObject', function() {
     var selectionController = new FakeSelectionController();
-    var controller = new tv.c.ScriptingController(selectionController);
+    var controller = new tr.c.ScriptingController(selectionController);
     controller.addScriptObject('z', 123);
     var result = controller.executeCommand('z');
     assert.equal(result, 123);
@@ -71,13 +71,13 @@
   test('scriptingControllerObjectRegistry', function() {
     var selectionController = new FakeSelectionController();
 
-    tv.c.ScriptingObjectRegistry.register(
+    tr.c.ScriptingObjectRegistry.register(
         function() { return 123; },
         {
           name: 'testFunctionName'
         }
     );
-    var controller = new tv.c.ScriptingController(selectionController);
+    var controller = new tr.c.ScriptingController(selectionController);
     var result = controller.executeCommand('testFunctionName()');
     assert.equal(result, 123);
   });
diff --git a/trace-viewer/trace_viewer/core/scripting_object.html b/trace-viewer/trace_viewer/core/scripting_object.html
index af9d1c3..c1914e1 100644
--- a/trace-viewer/trace_viewer/core/scripting_object.html
+++ b/trace-viewer/trace_viewer/core/scripting_object.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   function ScriptingObject() {
   }
 
diff --git a/trace-viewer/trace_viewer/core/selection.html b/trace-viewer/trace_viewer/core/selection.html
index 11e7dbf..df54682 100644
--- a/trace-viewer/trace_viewer/core/selection.html
+++ b/trace-viewer/trace_viewer/core/selection.html
@@ -9,7 +9,7 @@
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/base/range.html">
 <link rel="import" href="/base/iteration_helpers.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
@@ -17,11 +17,11 @@
 /**
  * @fileoverview Code for the viewport.
  */
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
 
-  var EventRegistry = tv.c.trace_model.EventRegistry;
+  var EventRegistry = tr.model.EventRegistry;
 
-  var RequestSelectionChangeEvent = tv.b.Event.bind(
+  var RequestSelectionChangeEvent = tr.b.Event.bind(
       undefined, 'requestSelectionChange', true, false);
 
   /**
@@ -36,9 +36,9 @@
     this.sunburst_zoom_level = undefined;
 
     this.bounds_dirty_ = true;
-    this.bounds_ = new tv.b.Range();
+    this.bounds_ = new tr.b.Range();
     this.length_ = 0;
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
     this.pushed_guids_ = {};
 
     if (opt_events) {
@@ -156,7 +156,7 @@
         });
         if (maxEventIndex == -1) {
           console.log(event);
-          throw new Error('Unrecgonized event type');
+          throw new Error('Unrecognized event type');
         }
         events[maxEventTypeInfo.metadata.name].push(event);
       });
@@ -198,14 +198,14 @@
       }
 
       var eventsByBaseType = this.getEventsOrganizedByBaseType(true);
-      var eventTypeName = tv.b.dictionaryKeys(eventsByBaseType)[0];
+      var eventTypeName = tr.b.dictionaryKeys(eventsByBaseType)[0];
 
       if (this.length === 1) {
         var tmp = EventRegistry.getUserFriendlySingularName(eventTypeName);
         return this[0].userFriendlyName;
       }
 
-      var numEventTypes = tv.b.dictionaryLength(eventsByBaseType);
+      var numEventTypes = tr.b.dictionaryLength(eventsByBaseType);
       if (numEventTypes !== 1) {
         return this.length + ' events of various types';
       }
@@ -231,7 +231,7 @@
 
         // If this is a flow event, then move to its slice based on the
         // offset direction.
-        if (event instanceof tv.c.trace_model.FlowEvent) {
+        if (event instanceof tr.model.FlowEvent) {
           if (offset > 0) {
             newSelection.push(event.endSlice);
           } else if (offset < 0) {
diff --git a/trace-viewer/trace_viewer/core/selection_controller.html b/trace-viewer/trace_viewer/core/selection_controller.html
index 4122f96..5a4b226 100644
--- a/trace-viewer/trace_viewer/core/selection_controller.html
+++ b/trace-viewer/trace_viewer/core/selection_controller.html
@@ -9,21 +9,21 @@
 <link rel="import" href="/base/task.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/brushing_state.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/ui_state.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
-  var BrushingState = tv.c.BrushingState;
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Viewport = tv.c.TimelineViewport;
+tr.exportTo('tr.c', function() {
+  var BrushingState = tr.c.BrushingState;
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
+  var Viewport = tr.c.TimelineViewport;
 
   function SelectionController(timelineView) {
-    tv.b.EventTarget.call(this);
+    tr.b.EventTarget.call(this);
 
     this.timelineView_ = timelineView;
     this.currentBrushingState_ = new BrushingState();
@@ -34,10 +34,10 @@
   }
 
   SelectionController.prototype = {
-    __proto__: tv.b.EventTarget.prototype,
+    __proto__: tr.b.EventTarget.prototype,
 
     dispatchChangeEvent_: function() {
-      var e = new tv.b.Event('change', false, false);
+      var e = new tr.b.Event('change', false, false);
       this.dispatchEvent(e);
     },
 
@@ -83,7 +83,7 @@
       this.selections_ = {};
       this.currentBrushingState_.applyToModelSelectionState(this.model);
 
-      var e = new tv.b.Event('model-changed', false, false);
+      var e = new tr.b.Event('model-changed', false, false);
       this.dispatchEvent(e);
     },
 
@@ -166,7 +166,7 @@
     addAllEventsMatchingFilterToSelectionAsTask: function(filter, selection) {
       var timelineView = this.timelineView_.trackView;
       if (!timelineView)
-        return new tv.b.Task();
+        return new tr.b.Task();
       return timelineView.addAllEventsMatchingFilterToSelectionAsTask(
           filter, selection);
     },
@@ -205,7 +205,7 @@
     },
 
     uiStateFromString: function(string) {
-      return tv.c.UIState.fromUserFriendlyString(
+      return tr.c.UIState.fromUserFriendlyString(
           this.model, this.viewport, string);
     },
 
diff --git a/trace-viewer/trace_viewer/core/selection_controller_test.html b/trace-viewer/trace_viewer/core/selection_controller_test.html
index 5ead94a..a314687 100644
--- a/trace-viewer/trace_viewer/core/selection_controller_test.html
+++ b/trace-viewer/trace_viewer/core/selection_controller_test.html
@@ -13,15 +13,15 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+tr.b.unittest.testSuite(function() {
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Task = tv.b.Task;
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
+  var Task = tr.b.Task;
 
   function newSimpleFakeTimelineView() {
-    var m = tv.c.test_utils.newModel(function(m) {
+    var m = tr.c.test_utils.newModel(function(m) {
       m.p1 = m.getOrCreateProcess(1);
       m.t2 = m.p1.getOrCreateThread(2);
 
@@ -53,11 +53,11 @@
 
   test('simpleStateChanges', function() {
     var timelineView = newSimpleFakeTimelineView();
-    var selectionController = new tv.c.SelectionController(timelineView);
+    var selectionController = new tr.c.SelectionController(timelineView);
     var m = timelineView.model;
 
     // Setting causes change.
-    var bs = new tv.c.BrushingState();
+    var bs = new tr.c.BrushingState();
     bs.selection = new Selection([m.sA]);
     assert.isTrue(doesCauseChangeToFire(
         selectionController,
@@ -77,7 +77,7 @@
     assert.isTrue(selectionController.currentBrushingState.isAppliedToModel);
 
     // Setting to something different unapplies the old bs.
-    var bs3 = new tv.c.BrushingState();
+    var bs3 = new tr.c.BrushingState();
     bs3.findMatches = new Selection([m.sA, m.sB]);
     selectionController.currentBrushingState = bs3;
     assert.isTrue(bs3.isAppliedToModel);
diff --git a/trace-viewer/trace_viewer/core/selection_test.html b/trace-viewer/trace_viewer/core/selection_test.html
index 675638d..e31d4e3 100644
--- a/trace-viewer/trace_viewer/core/selection_test.html
+++ b/trace-viewer/trace_viewer/core/selection_test.html
@@ -7,25 +7,25 @@
 
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/tracks/slice_track.html">
 <link rel="import" href="/core/tracks/drawing_container.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('selectionObject', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 5, {}, 1));
+        new tr.model.ThreadSlice('', 'a', 0, 5, {}, 1));
 
-    var sel = new tv.c.Selection();
+    var sel = new tr.c.Selection();
     sel.push(t1.sliceGroup.slices[0]);
 
     assert.equal(sel.bounds.min, 1);
@@ -42,23 +42,23 @@
   });
 
   test('shiftedSelection', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 5, {}, 1));
+        new tr.model.ThreadSlice('', 'a', 0, 5, {}, 1));
 
-    var viewport = new tv.c.TimelineViewport();
-    var track = new tv.c.tracks.SliceTrack(viewport);
+    var viewport = new tr.c.TimelineViewport();
+    var track = new tr.c.tracks.SliceTrack(viewport);
     viewport.modelTrackContainer = track;
     track.slices = t1.sliceGroup.slices;
 
     viewport.rebuildEventToTrackMap();
 
 
-    var sel = new tv.c.Selection();
+    var sel = new tr.c.Selection();
     sel.push(t1.sliceGroup.slices[0]);
 
     var shifted = sel.getShiftedSelection(track.viewport, 1);
@@ -70,7 +70,7 @@
     var sample1 = {guid: 1};
     var sample2 = {guid: 2};
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
 
     selection.push(sample1);
     selection.push(sample2);
@@ -81,24 +81,24 @@
   });
 
   test('userFriendlyNameSingular', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
-    var selection = new tv.c.Selection(t1.sliceGroup.slices[0]);
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+    var selection = new tr.c.Selection(t1.sliceGroup.slices[0]);
     assert.isDefined(selection.userFriendlyName);
   });
 
   test('userFriendlyNamePlural', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 2, {}, 3));
-    var selection = new tv.c.Selection([
+        new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
+    var selection = new tr.c.Selection([
         t1.sliceGroup.slices[0],
         t1.sliceGroup.slices[1]
     ]);
@@ -106,19 +106,19 @@
   });
 
   test('userFriendlyNameMixedPlural', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 2, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
 
-    var i10 = new tv.c.trace_model.ObjectInstance(
+    var i10 = new tr.model.ObjectInstance(
     {}, '0x1000', 'cat', 'name', 10);
     var s10 = i10.addSnapshot(10, {foo: 1});
 
-    var selection = new tv.c.Selection([
+    var selection = new tr.c.Selection([
         t1.sliceGroup.slices[0],
         s10
     ]);
@@ -126,23 +126,23 @@
   });
 
   test('groupEventsByTitle', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 2, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'b', 0, 3, {}, 3));
-    var selection = new tv.c.Selection([
+        new tr.model.ThreadSlice('', 'b', 0, 3, {}, 3));
+    var selection = new tr.c.Selection([
         t1.sliceGroup.slices[0],
         t1.sliceGroup.slices[1],
         t1.sliceGroup.slices[2]
     ]);
 
     var eventsByTitle = selection.getEventsOrganizedByTitle();
-    assert.equal(2, tv.b.dictionaryLength(eventsByTitle));
+    assert.equal(2, tr.b.dictionaryLength(eventsByTitle));
     assert.sameMembers(eventsByTitle['a'],
                  [t1.sliceGroup.slices[0], t1.sliceGroup.slices[1]]);
     assert.sameMembers(eventsByTitle['b'],
@@ -150,34 +150,34 @@
   });
 
   test('equals', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'b', 0, 2, {}, 3));
+        new tr.model.ThreadSlice('', 'b', 0, 2, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'c', 0, 3, {}, 3));
+        new tr.model.ThreadSlice('', 'c', 0, 3, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'd', 0, 4, {}, 5));
+        new tr.model.ThreadSlice('', 'd', 0, 4, {}, 5));
 
-    var s1 = new tv.c.Selection([
+    var s1 = new tr.c.Selection([
         t1.sliceGroup.slices[0],
         t1.sliceGroup.slices[1],
         t1.sliceGroup.slices[2]
     ]);
-    var s2 = new tv.c.Selection([
+    var s2 = new tr.c.Selection([
         t1.sliceGroup.slices[1],
         t1.sliceGroup.slices[0],
         t1.sliceGroup.slices[2]
     ]);
-    var s3 = new tv.c.Selection([
+    var s3 = new tr.c.Selection([
         t1.sliceGroup.slices[1],
         t1.sliceGroup.slices[0],
         t1.sliceGroup.slices[3]
     ]);
-    var s4 = new tv.c.Selection([
+    var s4 = new tr.c.Selection([
         t1.sliceGroup.slices[1],
         t1.sliceGroup.slices[0]
     ]);
diff --git a/trace-viewer/trace_viewer/core/side_panel/side_panel.html b/trace-viewer/trace_viewer/core/side_panel/side_panel.html
index fc12681..660f23c 100644
--- a/trace-viewer/trace_viewer/core/side_panel/side_panel.html
+++ b/trace-viewer/trace_viewer/core/side_panel/side_panel.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/base/ui.html">
 
-<polymer-element name='tv-c-side-panel'>
+<polymer-element name='tr-c-side-panel'>
   <script>
   'use strict';
   Polymer({
@@ -41,6 +41,10 @@
 
     get listeningToKeys() {
       throw new Error('Not implemented');
+    },
+
+    supportsModel: function(m) {
+      throw new Error('Not implemented');
     }
   });
   </script>
diff --git a/trace-viewer/trace_viewer/core/side_panel/side_panel_container.html b/trace-viewer/trace_viewer/core/side_panel/side_panel_container.html
index dfe0d55..dd889aa 100644
--- a/trace-viewer/trace_viewer/core/side_panel/side_panel_container.html
+++ b/trace-viewer/trace_viewer/core/side_panel/side_panel_container.html
@@ -9,7 +9,7 @@
 <link rel="import" href="/base/range.html">
 <link rel="import" href="/core/side_panel/side_panel.html">
 
-<polymer-element name='tv-c-side-panel-container' is='HTMLUnknownElement'>
+<polymer-element name='tr-c-side-panel-container' is='HTMLUnknownElement'>
   <template>
     <style>
     :host {
@@ -77,7 +77,7 @@
       this.activePanelContainer_ = this.$.active_panel_container;
       this.tabStrip_ = this.$.tab_strip;
 
-      this.rangeOfInterest_ = new tv.b.Range();
+      this.rangeOfInterest_ = new tr.b.Range();
       this.selectionController_ = undefined;
       this.onSelectionChanged_ = this.onSelectionChanged_.bind(this);
       this.onModelChanged_ = this.onModelChanged_.bind(this);
@@ -191,7 +191,7 @@
       this.tabStrip_.textContent = '';
       var supportedPanelTypes = [];
 
-      var panelTypes = tv.b.getPolymerElementsThatSubclass('tv-c-side-panel');
+      var panelTypes = tr.b.getPolymerElementsThatSubclass('tr-c-side-panel');
       panelTypes.forEach(function(panelType) {
         var labelEl = document.createElement('tab-strip-label');
         var panel = document.createElement(panelType);
diff --git a/trace-viewer/trace_viewer/core/side_panel/side_panel_container_test.html b/trace-viewer/trace_viewer/core/side_panel/side_panel_container_test.html
index bfe2822..71c856b 100644
--- a/trace-viewer/trace_viewer/core/side_panel/side_panel_container_test.html
+++ b/trace-viewer/trace_viewer/core/side_panel/side_panel_container_test.html
@@ -6,21 +6,21 @@
 -->
 
 <link rel="import" href="/core/side_panel/side_panel.html">
-<link rel="import" href="/extras/side_panel/time_summary.html">
+<link rel="import" href="/extras/side_panel/time_summary_side_panel.html">
 <link rel="import" href="/core/side_panel/side_panel_container.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function FakeSelectionController() {
     this.addAllEventsMatchingFilterToSelectionReturnValue = [];
 
     this.viewport = undefined;
     this.model = undefined;
-    this.selection = new tv.c.Selection();
-    this.highlight = new tv.c.Selection();
+    this.selection = new tr.c.Selection();
+    this.highlight = new tr.c.Selection();
   }
 
   FakeSelectionController.prototype = {
@@ -29,7 +29,7 @@
   };
 
   function createModel() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([], false, false, function() {
       var browserProcess = m.getOrCreateProcess(1);
       var browserMain = browserProcess.getOrCreateThread(2);
@@ -45,7 +45,7 @@
     var selectionController = new FakeSelectionController();
     selectionController.model = createModel();
 
-    var container = document.createElement('tv-c-side-panel-container');
+    var container = document.createElement('tr-c-side-panel-container');
     container.selectionController = selectionController;
     this.addHTMLOutput(container);
   });
diff --git a/trace-viewer/trace_viewer/core/test_utils.html b/trace-viewer/trace_viewer/core/test_utils.html
index 8ebde78..0678ef6 100644
--- a/trace-viewer/trace_viewer/core/test_utils.html
+++ b/trace-viewer/trace_viewer/core/test_utils.html
@@ -5,12 +5,12 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/counter.html">
-<link rel="import" href="/core/trace_model/slice.html">
-<link rel="import" href="/core/trace_model/slice_group.html">
-<link rel="import" href="/core/trace_model/stack_frame.html">
-<link rel="import" href="/core/trace_model/thread_time_slice.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/counter.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/slice.html">
+<link rel="import" href="/model/slice_group.html">
+<link rel="import" href="/model/stack_frame.html">
+<link rel="import" href="/model/thread_time_slice.html">
 
 <script>
 'use strict';
@@ -18,14 +18,58 @@
 /**
  * @fileoverview Helper functions for use in tracing tests.
  */
-tv.exportTo('tv.c.test_utils', function() {
+tr.exportTo('tr.c.test_utils', function() {
+  function _getStartAndCpuDurationFromDict(
+      options, required, startFieldName, durationFieldName, endFieldName) {
+
+    if (options[startFieldName] === undefined) {
+      if (required)
+        throw new Error('Too little information.');
+      else
+        return {start: undefined, duration: undefined};
+    }
+    if (options[durationFieldName] !== undefined &&
+        options[endFieldName] !== undefined) {
+      throw new Error('Too much information.');
+    }
+    if (options[durationFieldName] === undefined &&
+        options[endFieldName] === undefined) {
+      if (required)
+        throw new Error('Too little information.');
+      else
+        return {start: undefined, duration: undefined};
+    }
+
+    var duration;
+    if (options[durationFieldName] !== undefined) {
+      duration = options[durationFieldName];
+    } else {
+      duration = options[endFieldName] - options[startFieldName];
+    }
+
+    return {
+      start: options[startFieldName],
+      duration: duration
+    };
+  }
+
+  function getStartAndDurationFromDict(options) {
+    return _getStartAndCpuDurationFromDict(
+        options, true, 'start', 'duration', 'end');
+  }
+
+  function maybeGetCpuStartAndCpuDurationFromDict(options) {
+    return _getStartAndCpuDurationFromDict(
+        options, false, 'cpuStart', 'cpuDuration', 'cpuEnd');
+  }
+
   function newAsyncSlice(start, duration, startThread, endThread) {
     return newAsyncSliceNamed('a', start, duration, startThread, endThread);
   }
 
   function newAsyncSliceNamed(name, start, duration, startThread, endThread) {
     var asyncSliceConstructor =
-        tv.c.trace_model.AsyncSlice.getConstructor('', name);
+        tr.model.AsyncSlice.getConstructor('', name);
 
     var s = new asyncSliceConstructor('', name, 0, start);
     s.duration = duration;
@@ -35,8 +79,7 @@
   }
 
   function newAsyncSliceEx(options) {
-    if (options.start === undefined)
-      throw new Error('Too little info');
+    var sd = getStartAndDurationFromDict(options);
 
     var cat = options.cat ? options.cat : 'cat';
     var title = options.title ? options.title : 'a';
@@ -45,7 +88,7 @@
     if (options.colorId) {
       if (options.colorId === 'random') {
         colorId = Math.floor(Math.random() *
-                   tv.b.ui.paletteProperties.numGeneralPurposeColorIds);
+                   tr.b.ui.paletteProperties.numGeneralPurposeColorIds);
       } else {
         colorId = options.colorId;
       }
@@ -54,17 +97,6 @@
     }
 
 
-    var duration;
-    if (options.duration !== undefined) {
-      if (options.end !== undefined) throw new Error('TMI');
-      duration = options.duration;
-    } else if (options.end !== undefined) {
-      if (options.duration !== undefined) throw new Error('TMI');
-      duration = options.end - options.start;
-    } else {
-      throw new Error('Too little info');
-    }
-
     var isTopLevel;
     if (options.isTopLevel !== undefined)
       isTopLevel = options.isTopLevel;
@@ -72,20 +104,20 @@
       isTopLevel = false;
 
     var asyncSliceConstructor =
-        tv.c.trace_model.AsyncSlice.getConstructor(cat, title);
+        tr.model.AsyncSlice.getConstructor(cat, title);
 
     var slice = new asyncSliceConstructor(
         cat,
         title,
         colorId,
-        options.start,
+        sd.start,
         options.args ? options.args : {},
-        duration, isTopLevel);
+        sd.duration, isTopLevel);
 
     if (options.id)
       slice.id = options.id;
     else
-      slice.id = tv.b.GUID.allocate();
+      slice.id = tr.b.GUID.allocate();
 
     if (options.startStackFrame)
       slice.startStackFrame = options.startStackFrame;
@@ -105,17 +137,17 @@
   }
 
   function newCounterNamed(parent, name) {
-    var s = new tv.c.trace_model.Counter(parent, name, null, name);
+    var s = new tr.model.Counter(parent, name, null, name);
     return s;
   }
 
   function newCounterCategory(parent, category, name) {
-    var s = new tv.c.trace_model.Counter(parent, name, category, name);
+    var s = new tr.model.Counter(parent, name, category, name);
     return s;
   }
 
   function newCounterSeries() {
-    var s = new tv.c.trace_model.CounterSeries('a', 0);
+    var s = new tr.model.CounterSeries('a', 0);
     return s;
   }
 
@@ -127,31 +159,22 @@
 
     var colorId = options.colorId ? options.colorId : 0;
 
-    var duration;
-    if (options.duration !== undefined) {
-      if (options.end !== undefined) throw new Error('TMI');
-      duration = options.duration;
-    } else if (options.end !== undefined) {
-      if (options.duration !== undefined) throw new Error('TMI');
-      duration = options.end - options.start;
-    } else {
-      throw new Error('Too little info');
-    }
+    var sd = getStartAndDurationFromDict(options);
 
     var id;
     if (options.id !== undefined)
       id = options.id;
     else
-      id = tv.b.GUID.allocate();
+      id = tr.b.GUID.allocate();
 
-    var event = new tv.c.trace_model.FlowEvent(
+    var event = new tr.model.FlowEvent(
         options.cat ? options.cat : 'cat',
         id,
         title,
         colorId,
-        options.start,
+        sd.start,
         options.args ? options.args : {},
-        duration);
+        sd.duration);
 
     if (options.startStackFrame)
       event.startStackFrame = options.startStackFrame;
@@ -175,12 +198,12 @@
   }
 
   function newSliceNamed(name, start, duration) {
-    var s = new tv.c.trace_model.Slice('', name, 0, start, {}, duration);
+    var s = new tr.model.Slice('', name, 0, start, {}, duration);
     return s;
   }
 
   function newThreadSlice(thread, state, start, duration, opt_cpu) {
-    var s = new tv.c.trace_model.ThreadTimeSlice(
+    var s = new tr.model.ThreadTimeSlice(
         thread, state, 'cat', start, {}, duration);
     if (opt_cpu)
       s.cpuOnWhichThreadWasRunning = opt_cpu;
@@ -194,7 +217,7 @@
     else
       model = undefined;
     var sf = newStackTrace(model, category, frameNames);
-    var s = new tv.c.trace_model.Sample(undefined, thread,
+    var s = new tr.model.Sample(undefined, thread,
                                         sampleName, start,
                                         sf,
                                         1);
@@ -202,56 +225,34 @@
   }
 
   function newSliceCategory(category, name, start, duration) {
-    var s = new tv.c.trace_model.Slice(
+    var s = new tr.model.Slice(
         category, name, 0, start, {}, duration);
     return s;
   }
 
   function newSliceEx(options) {
-    if (options.start === undefined)
-      throw new Error('Too little info');
+    var sd = getStartAndDurationFromDict(options);
 
     var title = options.title ? options.title : 'a';
 
     var colorId = options.colorId ? options.colorId : 0;
 
-    var duration;
-    if (options.duration !== undefined) {
-      if (options.end !== undefined) throw new Error('TMI');
-      duration = options.duration;
-    } else if (options.end !== undefined) {
-      if (options.duration !== undefined) throw new Error('TMI');
-      duration = options.end - options.start;
-    } else {
-      throw new Error('Too little info');
-    }
-
-    var cpuStart = options.cpuStart;
-    var cpuDuration;
-    if (options.cpuDuration !== undefined) {
-      if (cpuStart !== undefined) throw new Error('Too little info');
-      if (options.cpuEnd !== undefined) throw new Error('TMI');
-      cpuDuration = options.cpuDuration;
-    } else if (options.cpuEnd !== undefined) {
-      if (cpuStart === undefined) throw new Error('Too little info');
-      if (options.cpuDuration !== undefined) throw new Error('TMI');
-      cpuDuration = options.cpuEnd - cpuStart;
-    }
+    var cpuSD = maybeGetCpuStartAndCpuDurationFromDict(options);
 
     var type;
     if (options.type)
       type = options.type;
     else
-      type = tv.c.trace_model.Slice;
+      type = tr.model.Slice;
 
     var slice = new type(
         options.cat ? options.cat : 'cat',
         title,
         colorId,
-        options.start,
+        sd.start,
         options.args ? options.args : {},
-        duration,
-        cpuStart, cpuDuration);
+        sd.duration,
+        cpuSD.start, cpuSD.duration);
 
 
     return slice;
@@ -260,7 +261,7 @@
   function newStackTrace(model, category, titles) {
     var frame = undefined;
     for (var i = 0; i < titles.length; i++) {
-      frame = new tv.c.trace_model.StackFrame(frame, tv.b.GUID.allocate(),
+      frame = new tr.model.StackFrame(frame, tr.b.GUID.allocate(),
                                                  category, titles[i], 7);
       if (model)
         model.addStackFrame(frame);
@@ -269,7 +270,7 @@
   }
 
   function findSliceNamed(slices, name) {
-    if (slices instanceof tv.c.trace_model.SliceGroup)
+    if (slices instanceof tr.model.SliceGroup)
       slices = slices.slices;
     for (var i = 0; i < slices.length; i++)
       if (slices[i].title == name)
@@ -278,23 +279,25 @@
   }
 
   function newModel(customizeModelCallback) {
-    var io = new tv.c.ImportOptions();
+    var io = new tr.ImportOptions();
     io.customizeModelCallback = customizeModelCallback;
     io.shiftWorldToZero = false;
     io.pruneEmptyContainers = false;
-    return new tv.c.TraceModel([], io);
+    io.auditorConstructors = [];
+    return new tr.Model([], io);
   }
 
   function newModelWithAuditor(customizeModelCallback, auditor) {
-    var io = new tv.c.ImportOptions();
+    var io = new tr.ImportOptions();
     io.customizeModelCallback = customizeModelCallback;
     io.shiftWorldToZero = false;
     io.pruneEmptyContainers = false;
     io.auditorConstructors = [auditor];
-    return new tv.c.TraceModel([], io);
+    return new tr.Model([], io);
   }
 
   return {
+    getStartAndDurationFromDict: getStartAndDurationFromDict,
     newAsyncSlice: newAsyncSlice,
     newAsyncSliceNamed: newAsyncSliceNamed,
     newAsyncSliceEx: newAsyncSliceEx,
diff --git a/trace-viewer/trace_viewer/core/timeline_display_transform.html b/trace-viewer/trace_viewer/core/timeline_display_transform.html
index 316795d..b6a13e9 100644
--- a/trace-viewer/trace_viewer/core/timeline_display_transform.html
+++ b/trace-viewer/trace_viewer/core/timeline_display_transform.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   function TimelineDisplayTransform(opt_that) {
     if (opt_that) {
       this.set(opt_that);
diff --git a/trace-viewer/trace_viewer/core/timeline_display_transform_animations.html b/trace-viewer/trace_viewer/core/timeline_display_transform_animations.html
index 0ff4910..993d141 100644
--- a/trace-viewer/trace_viewer/core/timeline_display_transform_animations.html
+++ b/trace-viewer/trace_viewer/core/timeline_display_transform_animations.html
@@ -10,13 +10,13 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   var kDefaultPanAnimatoinDurationMs = 100.0;
 
   /**
    * Pans a TimelineDisplayTransform by a given amount.
    * @constructor
-   * @extends {tv.b.ui.Animation}
+   * @extends {tr.b.ui.Animation}
    * @param {Number} deltaX The total amount of change to the transform's panX.
    * @param {Number} deltaY The total amount of change to the transform's panY.
    * @param {Number=} opt_durationMs How long the pan animation should run.
@@ -37,7 +37,7 @@
   }
 
   TimelineDisplayTransformPanAnimation.prototype = {
-    __proto__: tv.b.ui.Animation.prototype,
+    __proto__: tr.b.ui.Animation.prototype,
 
     get affectsPanY() {
       return this.deltaY !== 0;
@@ -67,11 +67,11 @@
 
     tick: function(timestamp, target) {
       var percentDone = (timestamp - this.startTimeMs) / this.durationMs;
-      percentDone = tv.b.clamp(percentDone, 0, 1);
+      percentDone = tr.b.clamp(percentDone, 0, 1);
 
-      target.panX = tv.b.lerp(percentDone, this.startPanX, this.goalPanX);
+      target.panX = tr.b.lerp(percentDone, this.startPanX, this.goalPanX);
       if (this.affectsPanY)
-        target.panY = tv.b.lerp(percentDone, this.startPanY, this.goalPanY);
+        target.panY = tr.b.lerp(percentDone, this.startPanY, this.goalPanY);
       return timestamp >= this.startTimeMs + this.durationMs;
     },
 
@@ -95,7 +95,7 @@
    * point in addition to the amount by which to zoom.
    *
    * @constructor
-   * @extends {tv.b.ui.Animation}
+   * @extends {tr.b.ui.Animation}
    * @param {Number} goalFocalPointXWorld The X coordinate in the world which is
    * of interest.
    * @param {Number} goalFocalPointXView Where on the screen the
@@ -127,7 +127,7 @@
   }
 
   TimelineDisplayTransformZoomToAnimation.prototype = {
-    __proto__: tv.b.ui.Animation.prototype,
+    __proto__: tr.b.ui.Animation.prototype,
 
     get affectsPanY() {
       return this.startPanY != this.goalFocalPointY;
@@ -150,11 +150,11 @@
 
     tick: function(timestamp, target) {
       var percentDone = (timestamp - this.startTimeMs) / this.durationMs;
-      percentDone = tv.b.clamp(percentDone, 0, 1);
+      percentDone = tr.b.clamp(percentDone, 0, 1);
 
-      target.scaleX = tv.b.lerp(percentDone, this.startScaleX, this.goalScaleX);
+      target.scaleX = tr.b.lerp(percentDone, this.startScaleX, this.goalScaleX);
       if (this.affectsPanY) {
-        target.panY = tv.b.lerp(
+        target.panY = tr.b.lerp(
             percentDone, this.startPanY, this.goalFocalPointY);
       }
 
diff --git a/trace-viewer/trace_viewer/core/timeline_display_transform_animations_test.html b/trace-viewer/trace_viewer/core/timeline_display_transform_animations_test.html
index 5b84a49..90b453d 100644
--- a/trace-viewer/trace_viewer/core/timeline_display_transform_animations_test.html
+++ b/trace-viewer/trace_viewer/core/timeline_display_transform_animations_test.html
@@ -12,12 +12,12 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
-  var TimelineDisplayTransform = tv.c.TimelineDisplayTransform;
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
+  var TimelineDisplayTransform = tr.c.TimelineDisplayTransform;
   var TimelineDisplayTransformPanAnimation =
-      tv.c.TimelineDisplayTransformPanAnimation;
+      tr.c.TimelineDisplayTransformPanAnimation;
   var TimelineDisplayTransformZoomToAnimation =
-      tv.c.TimelineDisplayTransformZoomToAnimation;
+      tr.c.TimelineDisplayTransformZoomToAnimation;
 
   test('panBasic', function() {
     var target = new TimelineDisplayTransform();
@@ -27,14 +27,14 @@
 
     var a = new TimelineDisplayTransformPanAnimation(10, 20, 100);
 
-    var controller = new tv.b.ui.AnimationController();
+    var controller = new tr.b.ui.AnimationController();
     controller.target = target;
     controller.queueAnimation(a, 0);
 
     assert.isTrue(a.affectsPanY);
-    tv.b.forcePendingRAFTasksToRun(50);
+    tr.b.forcePendingRAFTasksToRun(50);
     assert.isAbove(target.panX, 0);
-    tv.b.forcePendingRAFTasksToRun(100);
+    tr.b.forcePendingRAFTasksToRun(100);
     assert.isFalse(controller.hasActiveAnimation);
     assert.equal(target.panX, 10);
     assert.equal(target.panY, 20);
@@ -49,12 +49,12 @@
 
     var a = new TimelineDisplayTransformZoomToAnimation(10, 20, 30, 5, 100);
 
-    var controller = new tv.b.ui.AnimationController();
+    var controller = new tr.b.ui.AnimationController();
     controller.target = target;
     controller.queueAnimation(a, 0);
 
     assert.isFalse(a.affectsPanY);
-    tv.b.forcePendingRAFTasksToRun(100);
+    tr.b.forcePendingRAFTasksToRun(100);
     assert.equal(target.scaleX, 5);
   });
 
@@ -67,17 +67,17 @@
     var b = new TimelineDisplayTransformPanAnimation(10, 0, 100);
     var a = new TimelineDisplayTransformPanAnimation(10, 0, 100);
 
-    var controller = new tv.b.ui.AnimationController();
+    var controller = new tr.b.ui.AnimationController();
     controller.target = target;
     controller.queueAnimation(a, 0);
 
-    tv.b.forcePendingRAFTasksToRun(50);
+    tr.b.forcePendingRAFTasksToRun(50);
     controller.queueAnimation(b, 50);
 
-    tv.b.forcePendingRAFTasksToRun(100);
+    tr.b.forcePendingRAFTasksToRun(100);
     assert.isTrue(controller.hasActiveAnimation);
 
-    tv.b.forcePendingRAFTasksToRun(150);
+    tr.b.forcePendingRAFTasksToRun(150);
     assert.isFalse(controller.hasActiveAnimation);
     assert.equal(target.panX, 20);
   });
diff --git a/trace-viewer/trace_viewer/core/timeline_display_transform_test.html b/trace-viewer/trace_viewer/core/timeline_display_transform_test.html
index ab29107..d999cd7 100644
--- a/trace-viewer/trace_viewer/core/timeline_display_transform_test.html
+++ b/trace-viewer/trace_viewer/core/timeline_display_transform_test.html
@@ -10,8 +10,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TimelineDisplayTransform = tv.c.TimelineDisplayTransform;
+tr.b.unittest.testSuite(function() {
+  var TimelineDisplayTransform = tr.c.TimelineDisplayTransform;
 
   test('basics', function() {
     var a = new TimelineDisplayTransform();
diff --git a/trace-viewer/trace_viewer/core/timeline_interest_range.html b/trace-viewer/trace_viewer/core/timeline_interest_range.html
index fe33453..2632037 100644
--- a/trace-viewer/trace_viewer/core/timeline_interest_range.html
+++ b/trace-viewer/trace_viewer/core/timeline_interest_range.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   /**
    * @constructor
    */
@@ -27,7 +27,7 @@
   function TimelineInterestRange(vp) {
     this.viewport_ = vp;
 
-    this.range_ = new tv.b.Range();
+    this.range_ = new tr.b.Range();
 
     this.leftSelected_ = false;
     this.rightSelected_ = false;
@@ -85,7 +85,7 @@
     },
 
     asRangeObject: function() {
-      var range = new tv.b.Range();
+      var range = new tr.b.Range();
       range.addRange(this.range_);
       return range;
     },
@@ -180,7 +180,7 @@
       ctx.translate((Math.round(ctx.lineWidth) % 2) / 2, 0);
 
       ctx.beginPath();
-      tv.c.drawLine(ctx, viewX, 0, viewX, height);
+      tr.c.drawLine(ctx, viewX, 0, viewX, height);
       if (selected)
         ctx.strokeStyle = 'rgb(255, 0, 0)';
       else
@@ -225,12 +225,12 @@
         ctx.fillStyle = 'rgb(255, 0, 0)';
       else
         ctx.fillStyle = 'rgb(0, 0, 0)';
-      tv.c.drawTriangle(ctx,
+      tr.c.drawTriangle(ctx,
           viewX - arrowSize * 0.75, viewY,
           viewX + arrowSize * 0.75, viewY,
           viewX, viewY + arrowSize);
       ctx.fill();
-      tv.c.drawTriangle(ctx,
+      tr.c.drawTriangle(ctx,
           viewX - arrowSize * 0.75, viewY + viewHeight,
           viewX + arrowSize * 0.75, viewY + viewHeight,
           viewX, viewY + viewHeight - arrowSize);
diff --git a/trace-viewer/trace_viewer/core/timeline_track_view.html b/trace-viewer/trace_viewer/core/timeline_track_view.html
index ba9c40a..8d5c566 100644
--- a/trace-viewer/trace_viewer/core/timeline_track_view.html
+++ b/trace-viewer/trace_viewer/core/timeline_track_view.html
@@ -19,18 +19,18 @@
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/timeline_display_transform_animations.html">
 <link rel="import" href="/core/timing_tool.html">
-<link rel="import" href="/core/trace_model/event.html">
-<link rel="import" href="/core/trace_model/x_marker_annotation.html">
 <link rel="import" href="/core/tracks/drawing_container.html">
-<link rel="import" href="/core/tracks/trace_model_track.html">
+<link rel="import" href="/core/tracks/model_track.html">
 <link rel="import" href="/core/tracks/ruler_track.html">
+<link rel="import" href="/model/event.html">
+<link rel="import" href="/model/x_marker_annotation.html">
 
 <script>
 'use strict';
 
 /**
- * @fileoverview Interactive visualizaiton of TraceModel objects
- * based loosely on gantt charts. Each thread in the TraceModel is given a
+ * @fileoverview Interactive visualizaiton of Model objects
+ * based loosely on gantt charts. Each thread in the Model is given a
  * set of Tracks, one per subrow in the thread. The TimelineTrackView class
  * acts as a controller, creating the individual tracks, while Tracks
  * do actual drawing.
@@ -42,12 +42,12 @@
  *    Thread2:     CCCCCC                 CCCCC
  *
  */
-tv.exportTo('tv.c', function() {
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Viewport = tv.c.TimelineViewport;
+tr.exportTo('tr.c', function() {
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
+  var Viewport = tr.c.TimelineViewport;
 
-  var tempDisplayTransform = new tv.c.TimelineDisplayTransform();
+  var tempDisplayTransform = new tr.c.TimelineDisplayTransform();
 
   function intersectRect_(r1, r2) {
     var results = new Object;
@@ -65,7 +65,7 @@
   }
 
   /**
-   * Renders a TraceModel into a div element, making one
+   * Renders a Model into a div element, making one
    * Track for each subrow in each thread of the model, managing
    * overall track layout, and handling user interaction with the
    * viewport.
@@ -73,7 +73,7 @@
    * @constructor
    * @extends {HTMLDivElement}
    */
-  var TimelineTrackView = tv.b.ui.define('div');
+  var TimelineTrackView = tr.b.ui.define('div');
 
   TimelineTrackView.prototype = {
     __proto__: HTMLDivElement.prototype,
@@ -91,29 +91,29 @@
       this.selectionController_ = undefined;
 
       this.rulerTrackContainer_ =
-          new tv.c.tracks.DrawingContainer(this.viewport_);
+          new tr.c.tracks.DrawingContainer(this.viewport_);
       this.appendChild(this.rulerTrackContainer_);
       this.rulerTrackContainer_.invalidate();
 
-      this.rulerTrack_ = new tv.c.tracks.RulerTrack(this.viewport_);
+      this.rulerTrack_ = new tr.c.tracks.RulerTrack(this.viewport_);
       this.rulerTrackContainer_.appendChild(this.rulerTrack_);
 
-      this.upperModelTrack_ = new tv.c.tracks.TraceModelTrack(this.viewport_);
+      this.upperModelTrack_ = new tr.c.tracks.ModelTrack(this.viewport_);
       this.upperModelTrack_.upperMode = true;
       this.rulerTrackContainer_.appendChild(this.upperModelTrack_);
 
       this.modelTrackContainer_ =
-          new tv.c.tracks.DrawingContainer(this.viewport_);
+          new tr.c.tracks.DrawingContainer(this.viewport_);
       this.appendChild(this.modelTrackContainer_);
       this.modelTrackContainer_.style.display = 'block';
       this.modelTrackContainer_.invalidate();
 
       this.viewport_.modelTrackContainer = this.modelTrackContainer_;
 
-      this.modelTrack_ = new tv.c.tracks.TraceModelTrack(this.viewport_);
+      this.modelTrack_ = new tr.c.tracks.ModelTrack(this.viewport_);
       this.modelTrackContainer_.appendChild(this.modelTrack_);
 
-      this.timingTool_ = new tv.c.TimingTool(this.viewport_,
+      this.timingTool_ = new tr.c.TimingTool(this.viewport_,
                                                 this);
 
       this.initMouseModeSelector();
@@ -168,7 +168,7 @@
     },
 
     initMouseModeSelector: function() {
-      this.mouseModeSelector_ = new tv.b.ui.MouseModeSelector(this);
+      this.mouseModeSelector_ = new tr.b.ui.MouseModeSelector(this);
       this.appendChild(this.mouseModeSelector_);
 
       this.mouseModeSelector_.addEventListener('beginpan',
@@ -203,7 +203,7 @@
       this.mouseModeSelector_.addEventListener('exittiming',
           this.timingTool_.onExitTiming.bind(this.timingTool_));
 
-      var m = tv.b.ui.MOUSE_SELECTOR_MODE;
+      var m = tr.b.ui.MOUSE_SELECTOR_MODE;
       this.mouseModeSelector_.supportedModeMask =
           m.SELECTION | m.PANSCAN | m.ZOOM | m.TIMING;
       this.mouseModeSelector_.settingsKey =
@@ -220,11 +220,11 @@
       }.bind(this));
 
       this.mouseModeSelector_.setModifierForAlternateMode(
-          m.SELECTION, tv.b.ui.MODIFIER.SHIFT);
+          m.SELECTION, tr.b.ui.MODIFIER.SHIFT);
       this.mouseModeSelector_.setModifierForAlternateMode(
-          m.PANSCAN, tv.b.ui.MODIFIER.SPACE);
+          m.PANSCAN, tr.b.ui.MODIFIER.SPACE);
       this.mouseModeSelector_.setModifierForAlternateMode(
-          m.ZOOM, tv.b.ui.MODIFIER.CMD_OR_CTRL);
+          m.ZOOM, tr.b.ui.MODIFIER.CMD_OR_CTRL);
     },
 
     get selectionController() {
@@ -289,7 +289,7 @@
       if (modelInstanceChanged)
         this.viewport_.setWhenPossible(this.setInitialViewport_.bind(this));
 
-      tv.b.setPropertyAndDispatchChange(this, 'model', model);
+      tr.b.setPropertyAndDispatchChange(this, 'model', model);
     },
 
     get hasVisibleContent() {
@@ -374,7 +374,7 @@
       if (this.focusElement.tabIndex >= 0) {
         if (document.activeElement == this.focusElement)
           return true;
-        return tv.b.ui.elementIsChildOf(document.activeElement,
+        return tr.b.ui.elementIsChildOf(document.activeElement,
                                         this.focusElement);
       }
       return true;
@@ -523,7 +523,7 @@
 
     onDblClick_: function(e) {
       if (this.mouseModeSelector_.mode !==
-          tv.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
+          tr.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
         return;
 
       var curSelection = this.selectionController_.selection;
@@ -531,7 +531,7 @@
         return;
 
       var selection = new Selection();
-      var filter = new tv.c.ExactTitleFilter(curSelection[0].title);
+      var filter = new tr.c.ExactTitleFilter(curSelection[0].title);
       this.modelTrack_.addAllEventsMatchingFilterToSelection(filter,
                                                               selection);
 
@@ -550,7 +550,7 @@
 
     onMouseDown_: function(e) {
       if (this.mouseModeSelector_.mode !==
-          tv.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
+          tr.b.ui.MOUSE_SELECTOR_MODE.SELECTION)
         return;
       // Mouse down must start on ruler track for crosshair guide lines to draw.
       if (e.target !== this.rulerTrack_)
@@ -567,13 +567,13 @@
       }
 
       var dt = this.viewport_.currentDisplayTransform;
-      tv.b.ui.trackMouseMovesUntilMouseUp(function(e) { // Mouse move handler.
+      tr.b.ui.trackMouseMovesUntilMouseUp(function(e) { // Mouse move handler.
         // If mouse event is on ruler, don't do anything.
         if (e.target === this.rulerTrack_)
           return;
 
         var relativePosition = this.extractRelativeMousePosition_(e);
-        var loc = tv.c.Location.fromViewCoordinates(
+        var loc = tr.c.Location.fromViewCoordinates(
             this.viewport_, relativePosition.x, relativePosition.y);
         // Not all points on the timeline represents a valid location.
         // ex. process header tracks, letter dot tracks.
@@ -582,7 +582,7 @@
 
         if (this.guideLineAnnotation_ === undefined) {
           this.guideLineAnnotation_ =
-              new tv.c.trace_model.XMarkerAnnotation(loc.xWorld);
+              new tr.model.XMarkerAnnotation(loc.xWorld);
           this.model.addAnnotation(this.guideLineAnnotation_);
         } else {
           this.guideLineAnnotation_.timestamp = loc.xWorld;
@@ -590,7 +590,7 @@
         }
 
         // Set the findcontrol's text to nav string of current state.
-        var state = new tv.c.UIState(loc,
+        var state = new tr.c.UIState(loc,
             this.viewport_.currentDisplayTransform.scaleX);
         this.timelineView_.setFindCtlText(
             state.toUserFriendlyString(this.viewport_));
@@ -600,7 +600,7 @@
     queueSmoothPan_: function(viewDeltaX, deltaY) {
       var deltaX = this.viewport_.currentDisplayTransform.xViewVectorToWorld(
           viewDeltaX);
-      var animation = new tv.c.TimelineDisplayTransformPanAnimation(
+      var animation = new tr.c.TimelineDisplayTransformPanAnimation(
           deltaX, deltaY);
       this.viewport_.queueDisplayTransformAnimation(animation);
     },
@@ -624,7 +624,7 @@
       var goalFocalPointXWorld = vp.currentDisplayTransform.xViewToWorld(
           goalFocalPointXView);
       if (smooth) {
-        var animation = new tv.c.TimelineDisplayTransformZoomToAnimation(
+        var animation = new tr.c.TimelineDisplayTransformZoomToAnimation(
             goalFocalPointXWorld, goalFocalPointXView,
             vp.currentDisplayTransform.panY,
             scale);
@@ -657,7 +657,7 @@
       var zoomInRatio = newScale /
           this.viewport_.currentDisplayTransform.scaleX;
 
-      var animation = new tv.c.TimelineDisplayTransformZoomToAnimation(
+      var animation = new tr.c.TimelineDisplayTransformZoomToAnimation(
           worldCenter, viewCenter,
           this.viewport_.currentDisplayTransform.panY,
           zoomInRatio);
@@ -683,7 +683,7 @@
           tempDisplayTransform.xPanWorldPosToViewPos(
               worldCenter, 'center', viewWidth);
           var deltaX = tempDisplayTransform.panX - dt.panX;
-          var animation = new tv.c.TimelineDisplayTransformPanAnimation(
+          var animation = new tr.c.TimelineDisplayTransformPanAnimation(
               deltaX, 0);
           this.viewport_.queueDisplayTransformAnimation(animation);
         }
@@ -696,7 +696,7 @@
           bounds.max,
           viewWidth);
       var deltaX = tempDisplayTransform.panX - dt.panX;
-      var animation = new tv.c.TimelineDisplayTransformPanAnimation(
+      var animation = new tr.c.TimelineDisplayTransformPanAnimation(
           deltaX, 0);
       this.viewport_.queueDisplayTransformAnimation(animation);
     },
@@ -715,7 +715,7 @@
       track.scrollIntoViewIfNeeded();
 
       // Perform zoom and panX animation.
-      var animation = new tv.c.TimelineDisplayTransformZoomToAnimation(
+      var animation = new tr.c.TimelineDisplayTransformZoomToAnimation(
           worldCenter, viewCenter,
           this.viewport_.currentDisplayTransform.panY,
           zoomInRatio);
@@ -727,7 +727,7 @@
       if (this.xNavStringMarker_)
         this.model.removeAnnotation(this.xNavStringMarker_);
       this.xNavStringMarker_ =
-          new tv.c.trace_model.XMarkerAnnotation(worldCenter);
+          new tr.model.XMarkerAnnotation(worldCenter);
       this.model.addAnnotation(this.xNavStringMarker_);
     },
 
@@ -797,9 +797,9 @@
       var hiWX = dt.xViewToWorld(
           (hiX - canv.offsetLeft) * pixelRatio);
 
-      this.dragBox_.textContent = tv.c.analysis.tsString((hiWX - loWX));
+      this.dragBox_.textContent = tr.b.units.tsString((hiWX - loWX));
 
-      var e = new tv.b.Event('selectionChanging');
+      var e = new tr.b.Event('selectionChanging');
       e.loWX = loWX;
       e.hiWX = hiWX;
       this.dispatchEvent(e);
diff --git a/trace-viewer/trace_viewer/core/timeline_track_view_test.html b/trace-viewer/trace_viewer/core/timeline_track_view_test.html
index 8213672..590869f 100644
--- a/trace-viewer/trace_viewer/core/timeline_track_view_test.html
+++ b/trace-viewer/trace_viewer/core/timeline_track_view_test.html
@@ -13,13 +13,13 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Task = tv.b.Task;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
+  var Task = tr.b.Task;
 
   test('instantiate', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var num_threads = 500;
     model.importTraces([], false, false, function() {
       var p100 = model.getOrCreateProcess(100);
@@ -35,7 +35,7 @@
       }
     });
 
-    var timeline = new tv.c.TimelineTrackView();
+    var timeline = new tr.c.TimelineTrackView();
     timeline.model = model;
     timeline.focusElement = timeline;
     timeline.tabIndex = 0;
@@ -44,29 +44,29 @@
   });
 
   test('addAllEventsMatchingFilterToSelectionAsTask', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
 
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'a', 0, 1, {}, 3));
+        new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
     t1.sliceGroup.pushSlice(
-        new tv.c.trace_model.ThreadSlice('', 'b', 0, 1.1, {}, 2.8));
+        new tr.model.ThreadSlice('', 'b', 0, 1.1, {}, 2.8));
 
     var t1asg = t1.asyncSliceGroup;
     t1asg.slices.push(
-        tv.c.test_utils.newAsyncSliceNamed('a', 0, 1, t1, t1));
+        tr.c.test_utils.newAsyncSliceNamed('a', 0, 1, t1, t1));
     t1asg.slices.push(
-        tv.c.test_utils.newAsyncSliceNamed('b', 1, 2, t1, t1));
+        tr.c.test_utils.newAsyncSliceNamed('b', 1, 2, t1, t1));
 
-    var timeline = new tv.c.TimelineTrackView();
+    var timeline = new tr.c.TimelineTrackView();
     timeline.model = model;
 
     var expected = [t1asg.slices[0],
                     t1.sliceGroup.slices[0]];
-    var result = new tv.c.Selection();
+    var result = new tr.c.Selection();
     var filterTask = timeline.addAllEventsMatchingFilterToSelectionAsTask(
-        new tv.c.TitleOrCategoryFilter('a'), result);
+        new tr.c.TitleOrCategoryFilter('a'), result);
     Task.RunSynchronously(filterTask);
     assert.equal(result.length, 2);
     assert.equal(result[0], expected[0]);
@@ -74,9 +74,9 @@
 
     var expected = [t1asg.slices[1],
                     t1.sliceGroup.slices[1]];
-    var result = new tv.c.Selection();
+    var result = new tr.c.Selection();
     var filterTask = timeline.addAllEventsMatchingFilterToSelectionAsTask(
-        new tv.c.TitleOrCategoryFilter('b'), result);
+        new tr.c.TitleOrCategoryFilter('b'), result);
     Task.RunSynchronously(filterTask);
     assert.equal(result.length, 2);
     assert.equal(result[0], expected[0]);
@@ -84,62 +84,62 @@
   });
 
   test('emptyThreadsDeleted', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
 
-    var timeline = new tv.c.TimelineTrackView();
+    var timeline = new tr.c.TimelineTrackView();
     timeline.model = model;
 
     assert.isFalse(timeline.hasVisibleContent);
   });
 
   test('filteredCounters', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var c1 = model.kernel.getOrCreateCpu(0);
     c1.getOrCreateCounter('', 'b');
 
     var p1 = model.getOrCreateProcess(1);
     var ctr = p1.getOrCreateCounter('', 'a');
-    var series = new tv.c.trace_model.CounterSeries('a', 0);
+    var series = new tr.model.CounterSeries('a', 0);
     series.addCounterSample(0, 1);
     ctr.addSeries(series);
 
-    var timeline = new tv.c.TimelineTrackView();
+    var timeline = new tr.c.TimelineTrackView();
     timeline.model = model;
 
     assert.isTrue(timeline.hasVisibleContent);
   });
 
   test('filteredCpus', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var c1 = model.kernel.getOrCreateCpu(1);
     c1.getOrCreateCounter('', 'a');
 
-    var timeline = new tv.c.TimelineTrackView();
+    var timeline = new tr.c.TimelineTrackView();
     timeline.model = model;
 
     assert.isTrue(timeline.hasVisibleContent);
   });
 
   test('filteredProcesses', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     p1.getOrCreateCounter('', 'a');
 
-    var timeline = new tv.c.TimelineTrackView();
+    var timeline = new tr.c.TimelineTrackView();
     timeline.model = model;
 
     assert.isTrue(timeline.hasVisibleContent);
   });
 
   test('filteredThreads', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(2);
-    t1.sliceGroup.pushSlice(tv.c.test_utils.newSlice(0, 1));
+    t1.sliceGroup.pushSlice(tr.c.test_utils.newSlice(0, 1));
 
-    var timeline = new tv.c.TimelineTrackView();
+    var timeline = new tr.c.TimelineTrackView();
     timeline.model = model;
 
     assert.isTrue(timeline.hasVisibleContent);
@@ -154,8 +154,8 @@
       {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'},
       {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'}
     ];
-    var model = new tv.c.TraceModel(events);
-    var trackView = new tv.c.TimelineTrackView();
+    var model = new tr.Model(events);
+    var trackView = new tr.c.TimelineTrackView();
     trackView.model = model;
     this.addHTMLOutput(trackView);
 
@@ -172,8 +172,8 @@
       {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'},
       {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'}
     ];
-    var model = new tv.c.TraceModel(events);
-    var trackView = new tv.c.TimelineTrackView();
+    var model = new tr.Model(events);
+    var trackView = new tr.c.TimelineTrackView();
     trackView.model = model;
     this.addHTMLOutput(trackView);
     trackView.viewport.interestRange.reset();
@@ -189,8 +189,8 @@
       {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'},
       {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'}
     ];
-    var model = new tv.c.TraceModel(events);
-    var trackView = new tv.c.TimelineTrackView();
+    var model = new tr.Model(events);
+    var trackView = new tr.c.TimelineTrackView();
     trackView.model = model;
     this.addHTMLOutput(trackView);
     trackView.viewport.interestRange.reset();
diff --git a/trace-viewer/trace_viewer/core/timeline_view.css b/trace-viewer/trace_viewer/core/timeline_view.css
index 8f6f390..a3e5d9e 100644
--- a/trace-viewer/trace_viewer/core/timeline_view.css
+++ b/trace-viewer/trace_viewer/core/timeline_view.css
@@ -59,7 +59,7 @@
 
 x-timeline-view > .control > .bar > .controls button,
 x-timeline-view > .control > .bar > .controls label,
-x-timeline-view > .control > .bar > .controls tv-b-dropdown {
+x-timeline-view > .control > .bar > .controls tr-b-ui-dropdown {
   font-size: 14px;
   margin: 1px 2px 1px 2px;
 }
@@ -95,7 +95,7 @@
   -webkit-flex: 0 0 auto;
 }
 
-x-timeline-view > tv-c-a-analysis-view {
+x-timeline-view > tr-c-a-analysis-view {
   -webkit-flex: 0 0 auto;
 }
 
@@ -118,7 +118,7 @@
   text-align: center;
 }
 
-x-timeline-view > .control > .bar > .controls tv-b-dropdown {
+x-timeline-view > .control > .bar > .controls tr-b-ui-dropdown {
   font-size: 12px;
   height: 19px;
   background-color: #f8f8f8;
diff --git a/trace-viewer/trace_viewer/core/timeline_view.html b/trace-viewer/trace_viewer/core/timeline_view.html
index 084e21a..e46c2af 100644
--- a/trace-viewer/trace_viewer/core/timeline_view.html
+++ b/trace-viewer/trace_viewer/core/timeline_view.html
@@ -35,10 +35,10 @@
   </div>
   <middle-container>
     <track-view-container></track-view-container>
-    <tv-c-side-panel-container></tv-c-side-panel-container>
+    <tr-c-side-panel-container></tr-c-side-panel-container>
   </middle-container>
   <x-drag-handle></x-drag-handle>
-  <tv-c-a-analysis-view id="analysis"></tv-c-a-analysis-view>
+  <tr-c-a-analysis-view id="analysis"></tr-c-a-analysis-view>
 </template>
 
 <template id="help-btn-template">
@@ -212,9 +212,9 @@
 
 /**
  * @fileoverview View visualizes TRACE_EVENT events using the
- * tv.c.Timeline component and adds in selection summary and control buttons.
+ * tr.c.Timeline component and adds in selection summary and control buttons.
  */
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
   /**
@@ -222,13 +222,13 @@
    * @constructor
    * @extends {HTMLUnknownElement}
    */
-  var TimelineView = tv.b.ui.define('x-timeline-view');
+  var TimelineView = tr.b.ui.define('x-timeline-view');
 
   TimelineView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
 
     decorate: function() {
-      var node = tv.b.instantiateTemplate('#timeline-view-template', THIS_DOC);
+      var node = tr.b.instantiateTemplate('#timeline-view-template', THIS_DOC);
       this.appendChild(node);
 
       this.titleEl_ = this.querySelector('.title');
@@ -236,14 +236,14 @@
       this.rightControlsEl_ = this.querySelector('#right-controls');
       this.collapsingControlsEl_ = this.querySelector('#collapsing-controls');
       this.sidePanelContainer_ = this.querySelector(
-          'tv-c-side-panel-container');
+          'tr-c-side-panel-container');
       this.trackViewContainer_ = this.querySelector('track-view-container');
 
-      this.selectionController_ = new tv.c.SelectionController(this);
+      this.selectionController_ = new tr.c.SelectionController(this);
       this.selectionController_.historyEnabled = true;
 
       this.findCtl_ = new TracingFindControl();
-      this.findCtl_.controller = new tv.c.FindController(
+      this.findCtl_.controller = new tr.c.FindController(
           this.selectionController_);
       this.findCtl_.addEventListener('keydown', function(e) {
         if (e.keyCode === 27) { // ESC
@@ -253,23 +253,33 @@
       }.bind(this));
 
       this.scriptingCtl_ = new TracingScriptingControl();
-      this.scriptingCtl_.controller = new tv.c.ScriptingController(
+      this.scriptingCtl_.controller = new tr.c.ScriptingController(
           this.selectionController_);
 
       this.sidePanelContainer_.selectionController = this.selectionController_;
 
-      this.optionsDropdown_ = document.createElement('tv-b-dropdown');
+
+      if (window.tr.e && window.tr.e.rail && window.tr.e.rail.RAILScore) {
+        this.railScoreSpan_ = document.createElement(
+            'tr-e-rail-rail-score-span');
+        this.rightControls.appendChild(this.railScoreSpan_);
+      } else {
+        this.railScoreSpan_ = undefined;
+      }
+
+
+      this.optionsDropdown_ = document.createElement('tr-b-ui-dropdown');
       this.optionsDropdown_.iconElement.textContent = 'View Options';
 
       this.showFlowEvents_ = false;
-      this.optionsDropdown_.appendChild(tv.b.ui.createCheckBox(
+      this.optionsDropdown_.appendChild(tr.b.ui.createCheckBox(
           this, 'showFlowEvents',
-          'tv.c.TimelineView.showFlowEvents', false,
+          'tr.c.TimelineView.showFlowEvents', false,
           'Flow events'));
       this.highlightVSync_ = false;
-      this.highlightVSyncCheckbox_ = tv.b.ui.createCheckBox(
+      this.highlightVSyncCheckbox_ = tr.b.ui.createCheckBox(
           this, 'highlightVSync',
-          'tv.c.TimelineView.highlightVSync', false,
+          'tr.c.TimelineView.highlightVSync', false,
           'Highlight VSync');
       this.optionsDropdown_.appendChild(this.highlightVSyncCheckbox_);
 
@@ -282,7 +292,7 @@
       this.collapsingControls.appendChild(this.scriptingCtl_);
 
       this.dragEl_ = this.querySelector('x-drag-handle');
-      tv.b.ui.decorate(this.dragEl_, tv.b.ui.DragHandle);
+      tr.b.ui.decorate(this.dragEl_, tr.b.ui.DragHandle);
 
       this.analysisEl_ = this.querySelector('#analysis');
       this.analysisEl_.selectionController = this.selectionController_;
@@ -309,9 +319,9 @@
       else
         hue = this.model.faviconHue;
 
-      var faviconData = tv.c.FaviconsByHue[hue];
+      var faviconData = tr.c.FaviconsByHue[hue];
       if (faviconData === undefined)
-        faviconData = tv.c.FaviconsByHue['blue'];
+        faviconData = tr.c.FaviconsByHue['blue'];
 
       // Find link if its there
       var link = document.head.querySelector('link[rel="shortcut icon"]');
@@ -346,11 +356,11 @@
     },
 
     createHelpButton_: function() {
-      var node = tv.b.instantiateTemplate('#help-btn-template', THIS_DOC);
+      var node = tr.b.instantiateTemplate('#help-btn-template', THIS_DOC);
       var showEl = node.querySelector('.view-help-button');
       var helpTextEl = node.querySelector('.view-help-text');
 
-      var dlg = new tv.b.ui.Overlay();
+      var dlg = new tr.b.ui.Overlay();
       dlg.title = 'chrome://tracing Help';
       dlg.classList.add('view-help-overlay');
       dlg.appendChild(node);
@@ -358,7 +368,7 @@
       function onClick(e) {
         dlg.visible = !dlg.visible;
 
-        var mod = tv.isMac ? 'cmd ' : 'ctrl';
+        var mod = tr.isMac ? 'cmd ' : 'ctrl';
         var spans = helpTextEl.querySelectorAll('span.mod');
         for (var i = 0; i < spans.length; i++) {
           spans[i].textContent = mod;
@@ -374,7 +384,7 @@
     },
 
     createConsoleButton_: function() {
-      var node = tv.b.instantiateTemplate('#console-btn-template', THIS_DOC);
+      var node = tr.b.instantiateTemplate('#console-btn-template', THIS_DOC);
       var toggleEl = node.querySelector('.view-console-button');
 
       function onClick(e) {
@@ -388,11 +398,11 @@
     },
 
     createMetadataButton_: function() {
-      var node = tv.b.instantiateTemplate('#metadata-btn-template', THIS_DOC);
+      var node = tr.b.instantiateTemplate('#metadata-btn-template', THIS_DOC);
       var showEl = node.querySelector('.view-metadata-button');
       var textEl = node.querySelector('.info-button-text');
 
-      var dlg = new tv.b.ui.Overlay();
+      var dlg = new tr.b.ui.Overlay();
       dlg.title = 'Metadata for trace';
       dlg.classList.add('view-metadata-overlay');
       dlg.appendChild(node);
@@ -467,6 +477,8 @@
 
       // Remove old trackView if the model has completely changed.
       if (modelInstanceChanged) {
+        if (this.railScoreSpan_)
+          this.railScoreSpan_.railScore = undefined;
         this.trackViewContainer_.textContent = '';
         if (this.trackView_) {
           this.trackView_.viewport.removeEventListener(
@@ -480,7 +492,7 @@
 
       // Create new trackView if needed.
       if (modelValid && !this.trackView_) {
-        this.trackView_ = new tv.c.TimelineTrackView(this);
+        this.trackView_ = new tr.c.TimelineTrackView(this);
 
         this.trackView.selectionController = this.selectionController_;
 
@@ -496,11 +508,15 @@
         this.trackView_.model = model;
         this.trackView_.viewport.showFlowEvents = this.showFlowEvents;
         this.trackView_.viewport.highlightVSync = this.highlightVSync;
+        if (this.railScoreSpan_) {
+          var railScore = tr.e.rail.RAILScore.fromModel(model);
+          this.railScoreSpan_.railScore = railScore;
+        }
       }
 
       // Do things that are selection specific
       if (modelInstanceChanged) {
-        tv.b.dispatchSimpleEvent(this, 'modelChange');
+        tr.b.dispatchSimpleEvent(this, 'modelChange');
         this.selectionController_.modelDidChange();
         this.onViewportChanged_();
       }
@@ -516,7 +532,7 @@
 
     get settings() {
       if (!this.settings_)
-        this.settings_ = new tv.b.Settings();
+        this.settings_ = new tr.b.Settings();
       return this.settings_;
     },
 
@@ -542,7 +558,7 @@
     },
 
     get listenToKeys_() {
-      if (!tv.b.ui.isElementAttachedToDocument(this))
+      if (!tr.b.ui.isElementAttachedToDocument(this))
         return;
       if (document.activeElement.type === 'textarea')
         return false;
diff --git a/trace-viewer/trace_viewer/core/timeline_view_test.html b/trace-viewer/trace_viewer/core/timeline_view_test.html
index 090db1d..ba71d41 100644
--- a/trace-viewer/trace_viewer/core/timeline_view_test.html
+++ b/trace-viewer/trace_viewer/core/timeline_view_test.html
@@ -8,14 +8,14 @@
 <link rel="import" href="/base/task.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_view.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-  var Task = tv.b.Task;
+tr.b.unittest.testSuite(function() {
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+  var Task = tr.b.Task;
 
   var createFullyPopulatedModel = function(opt_withError, opt_withMetadata) {
     var withError = opt_withError !== undefined ? opt_withError : true;
@@ -26,33 +26,33 @@
     var testIndex = 0;
     var startTime = 0;
 
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     for (testIndex = 0; testIndex < num_tests; ++testIndex) {
       var process = model.getOrCreateProcess(10000 + testIndex);
       if (testIndex % 2 == 0) {
         var thread = process.getOrCreateThread('Thread Name Here');
-        thread.sliceGroup.pushSlice(new tv.c.trace_model.Slice(
+        thread.sliceGroup.pushSlice(new tr.model.Slice(
             'foo', 'a', 0, startTime, {}, 1));
-        thread.sliceGroup.pushSlice(new tv.c.trace_model.Slice(
+        thread.sliceGroup.pushSlice(new tr.model.Slice(
             'bar', 'b', 0, startTime + 23, {}, 10));
       } else {
         var thread = process.getOrCreateThread('Name');
-        thread.sliceGroup.pushSlice(new tv.c.trace_model.Slice(
+        thread.sliceGroup.pushSlice(new tr.model.Slice(
             'foo', 'a', 0, startTime + 4, {}, 11));
-        thread.sliceGroup.pushSlice(new tv.c.trace_model.Slice(
+        thread.sliceGroup.pushSlice(new tr.model.Slice(
             'bar', 'b', 0, startTime + 22, {}, 14));
       }
     }
     var p1000 = model.getOrCreateProcess(1000);
     var objects = p1000.objects;
-    objects.idWasCreated('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 10);
-    objects.addSnapshot('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 10,
+    objects.idWasCreated('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 10);
+    objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 10,
                         'snapshot-1');
-    objects.addSnapshot('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 25,
+    objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 25,
                         'snapshot-2');
-    objects.addSnapshot('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 40,
+    objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 40,
                         'snapshot-3');
-    objects.idWasDeleted('0x1000', 'tv.e.cc', 'LayerTreeHostImpl', 45);
+    objects.idWasDeleted('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 45);
     model.updateCategories_();
 
     // Add a known problematic piece of data to test the import errors UI.
@@ -91,7 +91,7 @@
   test('instantiate', function() {
     var model11 = createFullyPopulatedModel(true, true);
 
-    var view = new tv.c.TimelineView();
+    var view = new tr.c.TimelineView();
     view.style.height = '400px';
     view.style.border = '1px solid black';
     view.model = model11;
@@ -102,7 +102,7 @@
     var model00 = createFullyPopulatedModel(false, false);
     var model11 = createFullyPopulatedModel(true, true);
 
-    var view = new tv.c.TimelineView();
+    var view = new tr.c.TimelineView();
     view.style.height = '400px';
     view.model = model00;
     view.model = undefined;
@@ -114,7 +114,7 @@
     var model = createFullyPopulatedModel(false, false);
 
     // Create a view with am model.
-    var view = new tv.c.TimelineView();
+    var view = new tr.c.TimelineView();
     view.style.height = '400px';
     view.model = model;
     var sc = view.selectionController;
@@ -125,8 +125,8 @@
     view.model = model;
 
     // Verify that the new bits of the model show up in the view.
-    var selection = new tv.c.Selection();
-    var filter = new tv.c.TitleOrCategoryFilter('somethingUnusual');
+    var selection = new tr.c.Selection();
+    var filter = new tr.c.TitleOrCategoryFilter('somethingUnusual');
     var filterTask = sc.addAllEventsMatchingFilterToSelectionAsTask(
         filter, selection);
     Task.RunSynchronously(filterTask);
diff --git a/trace-viewer/trace_viewer/core/timeline_viewport.html b/trace-viewer/trace_viewer/core/timeline_viewport.html
index d843b1d..0ae8758 100644
--- a/trace-viewer/trace_viewer/core/timeline_viewport.html
+++ b/trace-viewer/trace_viewer/core/timeline_viewport.html
@@ -19,9 +19,9 @@
 /**
  * @fileoverview Code for the viewport.
  */
-tv.exportTo('tv.c', function() {
-  var TimelineDisplayTransform = tv.c.TimelineDisplayTransform;
-  var TimelineInterestRange = tv.c.TimelineInterestRange;
+tr.exportTo('tr.c', function() {
+  var TimelineDisplayTransform = tr.c.TimelineDisplayTransform;
+  var TimelineInterestRange = tr.c.TimelineInterestRange;
 
   /**
    * ContainerToTrackObj is a class to handle building and accessing a map
@@ -60,7 +60,7 @@
    * ways.
    *
    * @constructor
-   * @extends {tv.b.EventTarget}
+   * @extends {tr.b.EventTarget}
    */
   function TimelineViewport(parentEl) {
     this.parentEl_ = parentEl;
@@ -103,7 +103,7 @@
   }
 
   TimelineViewport.prototype = {
-    __proto__: tv.b.EventTarget.prototype,
+    __proto__: tr.b.EventTarget.prototype,
 
     /**
      * Allows initialization of the viewport when the viewport's parent element
@@ -123,7 +123,7 @@
       // Allow not providing a parent element, used by tests.
       if (this.parentEl_ === undefined)
         return;
-      return tv.b.ui.isElementAttachedToDocument(this.parentEl_);
+      return tr.b.ui.isElementAttachedToDocument(this.parentEl_);
     },
 
     onResize_: function() {
@@ -170,7 +170,7 @@
      * to redraw when the underlying model has been mutated.
      */
     dispatchChangeEvent: function() {
-      tv.b.dispatchSimpleEvent(this, 'change');
+      tr.b.dispatchSimpleEvent(this, 'change');
     },
 
     detach: function() {
@@ -185,7 +185,7 @@
     },
 
     initAnimationController_: function() {
-      this.dtAnimationController_ = new tv.b.ui.AnimationController();
+      this.dtAnimationController_ = new tr.b.ui.AnimationController();
       this.dtAnimationController_.addEventListener(
           'didtick', function(e) {
             this.onCurentDisplayTransformChange_(e.oldTargetState);
@@ -242,15 +242,15 @@
     },
 
     queueDisplayTransformAnimation: function(animation) {
-      if (!(animation instanceof tv.b.ui.Animation))
-        throw new Error('animation must be instanceof tv.b.ui.Animation');
+      if (!(animation instanceof tr.b.ui.Animation))
+        throw new Error('animation must be instanceof tr.b.ui.Animation');
       this.dtAnimationController_.queueAnimation(animation);
     },
 
     onCurentDisplayTransformChange_: function(oldDisplayTransform) {
       // Ensure panY stays clamped in the track container's scroll range.
       if (this.modelTrackContainer_) {
-        this.currentDisplayTransform.panY = tv.b.clamp(
+        this.currentDisplayTransform.panY = tr.b.clamp(
             this.currentDisplayTransform.panY,
             0,
             this.modelTrackContainer_.scrollHeight -
@@ -355,7 +355,7 @@
       ctx.beginPath();
       for (var idx in this.majorMarkPositions) {
         var x = Math.floor(this.majorMarkPositions[idx]);
-        tv.c.drawLine(ctx, x, 0, x, ctx.canvas.height);
+        tr.c.drawLine(ctx, x, 0, x, ctx.canvas.height);
       }
       ctx.strokeStyle = '#ddd';
       ctx.stroke();
@@ -381,7 +381,7 @@
           // Do conversion to viewspace here rather than on
           // x to avoid precision issues.
           var vx = Math.floor(dt.xWorldToView(x));
-          tv.c.drawLine(ctx, vx, 0, vx, ctx.canvas.height);
+          tr.c.drawLine(ctx, vx, 0, vx, ctx.canvas.height);
         }
 
         x += this.gridStep;
diff --git a/trace-viewer/trace_viewer/core/timeline_viewport_test.html b/trace-viewer/trace_viewer/core/timeline_viewport_test.html
index ca8826e..bc78736 100644
--- a/trace-viewer/trace_viewer/core/timeline_viewport_test.html
+++ b/trace-viewer/trace_viewer/core/timeline_viewport_test.html
@@ -10,10 +10,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('memoization', function() {
 
-    var vp = new tv.c.TimelineViewport(document.createElement('div'));
+    var vp = new tr.c.TimelineViewport(document.createElement('div'));
 
     var slice = { guid: 1 };
 
diff --git a/trace-viewer/trace_viewer/core/timing_tool.html b/trace-viewer/trace_viewer/core/timing_tool.html
index 3156fbb..d370646 100644
--- a/trace-viewer/trace_viewer/core/timing_tool.html
+++ b/trace-viewer/trace_viewer/core/timing_tool.html
@@ -9,7 +9,7 @@
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/base/range.html">
 <link rel="import" href="/base/ui.html">
-<link rel="import" href="/core/trace_model/slice.html">
+<link rel="import" href="/model/slice.html">
 
 <script>
 'use strict';
@@ -17,9 +17,9 @@
 /**
  * @fileoverview Provides the TimingTool class.
  */
-tv.exportTo('tv.c', function() {
+tr.exportTo('tr.c', function() {
 
-  var constants = tv.c.constants;
+  var constants = tr.c.constants;
 
   /**
    * Tool for taking time measurements in the TimelineTrackView using
@@ -60,9 +60,9 @@
         return;
       var ir = this.viewport_.interestRange;
       if (ir.min === pt.x)
-        ir.leftSnapIndicator = new tv.c.SnapIndicator(pt.y, pt.height);
+        ir.leftSnapIndicator = new tr.c.SnapIndicator(pt.y, pt.height);
       if (ir.max === pt.x)
-        ir.rightSnapIndicator = new tv.c.SnapIndicator(pt.y, pt.height);
+        ir.rightSnapIndicator = new tr.c.SnapIndicator(pt.y, pt.height);
     },
 
     onUpdateTiming: function(e) {
@@ -251,7 +251,7 @@
       var worldX = this.getWorldXFromEvent_(e);
       var mouseY = e.clientY;
 
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
 
       // Look at the track under mouse position first for better performance.
       modelTrackContainer.addClosestEventToSelection(
@@ -277,7 +277,7 @@
         snapped: false
       };
 
-      var eventBounds = new tv.b.Range();
+      var eventBounds = new tr.b.Range();
       for (var i = 0; i < selection.length; i++) {
         var event = selection[i];
         var track = viewport.trackForEvent(event);
diff --git a/trace-viewer/trace_viewer/core/timing_tool_test.html b/trace-viewer/trace_viewer/core/timing_tool_test.html
index 81177f7..77a9e10 100644
--- a/trace-viewer/trace_viewer/core/timing_tool_test.html
+++ b/trace-viewer/trace_viewer/core/timing_tool_test.html
@@ -11,10 +11,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function create100PxWideViewportInto10WideWorld() {
-    var vp = new tv.c.TimelineViewport(document.createElement('div'));
-    var tempDisplayTransform = new tv.c.TimelineDisplayTransform();
+    var vp = new tr.c.TimelineViewport(document.createElement('div'));
+    var tempDisplayTransform = new tr.c.TimelineDisplayTransform();
     tempDisplayTransform.xSetWorldBounds(0, 10, 100);
     vp.setDisplayTransformImmediately(tempDisplayTransform);
 
@@ -28,7 +28,7 @@
     var vp = create100PxWideViewportInto10WideWorld();
     vp.interestRange.min = 1;
     vp.interestRange.max = 9;
-    var tool = new tv.c.TimingTool(vp);
+    var tool = new tr.c.TimingTool(vp);
 
     tool.mouseDownAt_(1.1, 0);
     assert.isTrue(vp.interestRange.leftSelected);
@@ -43,7 +43,7 @@
     var vp = create100PxWideViewportInto10WideWorld();
     vp.interestRange.min = 1;
     vp.interestRange.max = 9;
-    var tool = new tv.c.TimingTool(vp);
+    var tool = new tr.c.TimingTool(vp);
 
     tool.mouseDownAt_(9.1, 0);
     assert.isTrue(vp.interestRange.rightSelected);
@@ -58,7 +58,7 @@
     var vp = create100PxWideViewportInto10WideWorld();
     vp.interestRange.min = 1;
     vp.interestRange.max = 9;
-    var tool = new tv.c.TimingTool(vp);
+    var tool = new tr.c.TimingTool(vp);
 
     tool.mouseDownAt_(5, 0);
     assert.isTrue(vp.interestRange.rightSelected);
diff --git a/trace-viewer/trace_viewer/core/trace_model/async_slice_group_test.html b/trace-viewer/trace_viewer/core/trace_model/async_slice_group_test.html
deleted file mode 100644
index 9e2df29..0000000
--- a/trace-viewer/trace_viewer/core/trace_model/async_slice_group_test.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!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="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
-  var Process = tv.c.trace_model.Process;
-  var Thread = tv.c.trace_model.Thread;
-  var AsyncSlice = tv.c.trace_model.AsyncSlice;
-  var AsyncSliceGroup = tv.c.trace_model.AsyncSliceGroup;
-  var newAsyncSlice = tv.c.test_utils.newAsyncSlice;
-
-  test('asyncSliceGroupBounds_Empty', function() {
-    var thread = {};
-    var g = new AsyncSliceGroup(thread);
-    g.updateBounds();
-    assert.isTrue(g.bounds.isEmpty);
-  });
-
-  test('asyncSliceGroupBounds_Basic', function() {
-    var model = new tv.c.TraceModel();
-    var p1 = new Process(model, 1);
-    var t1 = new Thread(p1, 1);
-    var g = new AsyncSliceGroup(t1);
-    g.push(newAsyncSlice(0, 1, t1, t1));
-    g.push(newAsyncSlice(1, 1.5, t1, t1));
-    assert.equal(g.length, 2);
-    g.updateBounds();
-    assert.equal(g.bounds.min, 0);
-    assert.equal(g.bounds.max, 2.5);
-  });
-
-  test('asyncSliceGroupStableId', function() {
-    var model = new tv.c.TraceModel();
-    var process = model.getOrCreateProcess(123);
-    var thread = process.getOrCreateThread(456);
-    var group = new AsyncSliceGroup(thread);
-
-    assert.equal(process.stableId, 123);
-    assert.equal(thread.stableId, '123.456');
-    assert.equal(group.stableId, '123.456.AsyncSliceGroup');
-  });
-});
-</script>
-
diff --git a/trace-viewer/trace_viewer/core/trace_model/global_memory_dump.html b/trace-viewer/trace_viewer/core/trace_model/global_memory_dump.html
deleted file mode 100644
index b99ed47..0000000
--- a/trace-viewer/trace_viewer/core/trace_model/global_memory_dump.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2015 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="import" href="/core/trace_model/container_memory_dump.html">
-<link rel="import" href="/core/analysis/util.html">
-
-<script>
-'use strict';
-
-/**
- * @fileoverview Provides the GlobalMemoryDump class.
- */
-tv.exportTo('tv.c.trace_model', function() {
-  /**
-   * The GlobalMemoryDump represents a simultaneous memory dump of all
-   * processes.
-   * @constructor
-   */
-  function GlobalMemoryDump(model, start) {
-    tv.c.trace_model.ContainerMemoryDump.call(this, start);
-    this.model = model;
-    this.processMemoryDumps = {};
-  }
-
-  GlobalMemoryDump.prototype = {
-    __proto__: tv.c.trace_model.ContainerMemoryDump.prototype,
-
-    get userFriendlyName() {
-      return 'Global memory dump ' + ' at ' +
-          tv.c.analysis.tsString(this.start);
-    }
-  };
-
-  tv.c.trace_model.EventRegistry.register(
-      GlobalMemoryDump,
-      {
-        name: 'globalMemoryDump',
-        pluralName: 'globalMemoryDumps',
-        singleViewElementName: 'tv-c-single-global-memory-dump-sub-view',
-        multiViewElementName: 'tv-c-multi-global-memory-dump-sub-view'
-      });
-
-  return {
-    GlobalMemoryDump: GlobalMemoryDump
-  };
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/object_snapshot_test.html b/trace-viewer/trace_viewer/core/trace_model/object_snapshot_test.html
deleted file mode 100644
index ef4c063..0000000
--- a/trace-viewer/trace_viewer/core/trace_model/object_snapshot_test.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!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="import" href="/core/trace_model/object_instance.html">
-<link rel="import" href="/core/trace_model/object_snapshot.html">
-
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() {
-  test('snapshotTypeRegistry', function() {
-    function MySnapshot() {
-      tv.c.trace_model.ObjectSnapshot.apply(this, arguments);
-      this.myFoo = this.args.foo;
-    }
-
-    MySnapshot.prototype = {
-      __proto__: tv.c.trace_model.ObjectSnapshot.prototype
-    };
-
-    var instance = new tv.c.trace_model.ObjectInstance(
-        {}, '0x1000', 'cat', 'MySnapshot', 10);
-    try {
-      tv.c.trace_model.ObjectSnapshot.register(
-          MySnapshot,
-          {typeName: 'MySnapshot'});
-      var snapshot = instance.addSnapshot(15, {foo: 'bar'});
-      assert.instanceOf(snapshot, MySnapshot);
-      assert.equal(snapshot.myFoo, 'bar');
-    } finally {
-      tv.c.trace_model.ObjectSnapshot.unregister(MySnapshot);
-    }
-  });
-});
-</script>
-
diff --git a/trace-viewer/trace_viewer/core/trace_model/process_memory_dump.html b/trace-viewer/trace_viewer/core/trace_model/process_memory_dump.html
deleted file mode 100644
index fa1eeec..0000000
--- a/trace-viewer/trace_viewer/core/trace_model/process_memory_dump.html
+++ /dev/null
@@ -1,165 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2015 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="import" href="/core/trace_model/container_memory_dump.html">
-<link rel="import" href="/core/analysis/util.html">
-
-<script>
-'use strict';
-
-/**
- * @fileoverview Provides the ProcessMemoryDump class.
- */
-tv.exportTo('tv.c.trace_model', function() {
-  /**
-   * The ProcessMemoryDump represents a memory dump of a single process.
-   * @constructor
-   */
-  function ProcessMemoryDump(globalMemoryDump, process, start) {
-    tv.c.trace_model.ContainerMemoryDump.call(this, start);
-    this.process = process;
-    this.globalMemoryDump = globalMemoryDump;
-
-    this.totalResidentBytes = undefined;
-    this.vmRegions_ = undefined;
-  };
-
-  ProcessMemoryDump.prototype = {
-    __proto__: tv.c.trace_model.ContainerMemoryDump.prototype,
-
-    get userFriendlyName() {
-      return 'Process memory dump at ' + tv.c.analysis.tsString(this.start);
-    },
-
-    get vmRegions() {
-      throw new Error(
-          'VM regions must be accessed through the mostRecentVmRegions field');
-    },
-
-    set vmRegions(vmRegions) {
-      this.vmRegions_ = vmRegions;
-    },
-
-    getMostRecentTotalVmRegionStat_: function(statGetterFn) {
-      if (this.mostRecentVmRegions === undefined)
-        return undefined;
-
-      var total = 0;
-      this.mostRecentVmRegions.forEach(function(vmRegion) {
-        total += statGetterFn(vmRegion);
-      });
-      return total;
-    },
-
-    get mostRecentTotalProportionalResidentSizeInBytes() {
-      return this.getMostRecentTotalVmRegionStat_(function(vmRegion) {
-        return vmRegion.byteStats.proportionalResident;
-      });
-    },
-
-    get mostRecentTotalPrivateResidentSizeInBytes() {
-      return this.getMostRecentTotalVmRegionStat_(function(vmRegion) {
-        return vmRegion.byteStats.privateResident;
-      });
-    },
-
-    get mostRecentTotalSharedResidentSizeInBytes() {
-      return this.getMostRecentTotalVmRegionStat_(function(vmRegion) {
-        return vmRegion.byteStats.sharedResident;
-      });
-    }
-  };
-
-  ProcessMemoryDump.hookUpMostRecentVmRegionsLinks = function(processDumps) {
-    var mostRecentVmRegions = undefined;
-
-    processDumps.forEach(function(processDump) {
-      // Update the most recent VM regions from the current dump.
-      if (processDump.vmRegions_ !== undefined)
-        mostRecentVmRegions = processDump.vmRegions_;
-
-      // Set the most recent VM regions of the current dump.
-      processDump.mostRecentVmRegions = mostRecentVmRegions;
-    });
-  };
-
-  /**
-   * @constructor
-   */
-  function VMRegion(startAddress, sizeInBytes, protectionFlags,
-      mappedFile, byteStats) {
-    this.startAddress = startAddress;
-    this.sizeInBytes = sizeInBytes;
-    this.protectionFlags = protectionFlags;
-    this.mappedFile = mappedFile;
-    this.byteStats = byteStats;
-  };
-
-  VMRegion.PROTECTION_FLAG_READ = 4;
-  VMRegion.PROTECTION_FLAG_WRITE = 2;
-  VMRegion.PROTECTION_FLAG_EXECUTE = 1;
-
-  VMRegion.prototype = {
-    get protectionFlagsToString() {
-      if (this.protectionFlags === undefined)
-        return undefined;
-      return (
-          (this.protectionFlags & VMRegion.PROTECTION_FLAG_READ ? 'r' : '-') +
-          (this.protectionFlags & VMRegion.PROTECTION_FLAG_WRITE ? 'w' : '-') +
-          (this.protectionFlags & VMRegion.PROTECTION_FLAG_EXECUTE ? 'x' : '-')
-      );
-    }
-  };
-
-  VMRegion.fromDict = function(dict) {
-    return new VMRegion(
-        dict.startAddress,
-        dict.sizeInBytes,
-        dict.protectionFlags,
-        dict.mappedFile,
-        VMRegionByteStats.fromDict(dict.byteStats));
-  };
-
-  /**
-   * @constructor
-   */
-  function VMRegionByteStats(privateResident, sharedResident,
-      proportionalResident) {
-    this.privateResident = privateResident;
-    this.sharedResident = sharedResident;
-    this.proportionalResident = proportionalResident;
-  };
-
-  VMRegionByteStats.prototype = {
-    get totalResident() {
-      return this.privateResident + this.sharedResident;
-    }
-  };
-
-  VMRegionByteStats.fromDict = function(dict) {
-    return new VMRegionByteStats(
-        dict.privateResident,
-        dict.sharedResident,
-        dict.proportionalResident);
-  };
-
-  tv.c.trace_model.EventRegistry.register(
-      ProcessMemoryDump,
-      {
-        name: 'processMemoryDump',
-        pluralName: 'processMemoryDumps',
-        singleViewElementName: 'tv-c-single-process-memory-dump-sub-view',
-        multiViewElementName: 'tv-c-multi-process-memory-dump-sub-view'
-      });
-
-  return {
-    ProcessMemoryDump: ProcessMemoryDump,
-    VMRegion: VMRegion,
-    VMRegionByteStats: VMRegionByteStats
-  };
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/process_memory_dump_test.html b/trace-viewer/trace_viewer/core/trace_model/process_memory_dump_test.html
deleted file mode 100644
index eaa5d1f..0000000
--- a/trace-viewer/trace_viewer/core/trace_model/process_memory_dump_test.html
+++ /dev/null
@@ -1,224 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2015 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="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/attribute.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/trace_model/global_memory_dump.html">
-<link rel="import" href="/core/trace_model/process_memory_dump.html">
-
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() {
-  var TraceModel = tv.c.TraceModel;
-  var GlobalMemoryDump = tv.c.trace_model.GlobalMemoryDump;
-  var ProcessMemoryDump = tv.c.trace_model.ProcessMemoryDump;
-  var MemoryAllocatorDump = tv.c.trace_model.MemoryAllocatorDump;
-  var VMRegion = tv.c.trace_model.VMRegion;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
-
-  var createProcessMemoryDump = function(timestamp, model) {
-    var gmd = new GlobalMemoryDump(model, timestamp);
-    model.globalMemoryDumps.push(gmd);
-    var p = model.getOrCreateProcess(123);
-    var pmd = new ProcessMemoryDump(gmd, p, timestamp + 1);
-    p.memoryDumps.push(pmd);
-    return pmd;
-  }
-
-  var createFinalizedProcessMemoryDump = function(timestamp, createdCallback) {
-    var model = tv.c.test_utils.newModel(function(model) {
-      createdCallback(createProcessMemoryDump(timestamp, model));
-    });
-    var pmds = model.getProcess(123).memoryDumps;
-    assert.lengthOf(pmds, 1);
-    return pmds[0];
-  }
-
-  function checkProtectionFlagsToString(protectionFlags, expectedString) {
-    var vmRegion = VMRegion.fromDict({
-      startAddress: 256,
-      sizeInBytes: 336,
-      protectionFlags: protectionFlags,
-      mappedFile: '[stack:20310]',
-      byteStats: {
-        privateResident: 96,
-        sharedResident: 144,
-        proportionalResident: 158
-      }
-    });
-    assert.strictEqual(vmRegion.protectionFlagsToString, expectedString);
-  }
-
-  test('totalResidentSizeInBytes_undefinedVmRegions', function() {
-    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {});
-    assert.isUndefined(pmd.mostRecentTotalProportionalResidentSizeInBytes);
-    assert.isUndefined(pmd.mostRecentTotalPrivateResidentSizeInBytes);
-    assert.isUndefined(pmd.mostRecentTotalSharedResidentSizeInBytes);
-  });
-
-  test('totalResidentSizeInBytes_zeroVmRegions', function() {
-    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
-      pmd.vmRegions = [];
-    });
-    assert.equal(pmd.mostRecentTotalProportionalResidentSizeInBytes, 0);
-    assert.equal(pmd.mostRecentTotalPrivateResidentSizeInBytes, 0);
-    assert.equal(pmd.mostRecentTotalSharedResidentSizeInBytes, 0);
-  });
-
-  test('totalResidentSizeInBytes_oneVmRegion', function() {
-    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
-      pmd.vmRegions = [
-        VMRegion.fromDict({
-          startAddress: 256,
-          sizeInBytes: 336,
-          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
-              VMRegion.PROTECTION_FLAG_WRITE,
-          mappedFile: '[stack:20310]',
-          byteStats: {
-            privateResident: 96,
-            sharedResident: 144,
-            proportionalResident: 158
-          }
-        })
-      ];
-    });
-    assert.equal(pmd.mostRecentTotalProportionalResidentSizeInBytes, 158);
-    assert.equal(pmd.mostRecentTotalPrivateResidentSizeInBytes, 96);
-    assert.equal(pmd.mostRecentTotalSharedResidentSizeInBytes, 144);
-  });
-
-  test('totalResidentSizeInBytes_twoVmRegions', function() {
-    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
-      pmd.vmRegions = [
-        VMRegion.fromDict({
-          startAddress: 256,
-          sizeInBytes: 336,
-          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
-              VMRegion.PROTECTION_FLAG_WRITE,
-          mappedFile: '[stack:20310]',
-          byteStats: {
-            privateResident: 96,
-            sharedResident: 144,
-            proportionalResident: 158
-          }
-        }),
-        VMRegion.fromDict({
-          startAddress: 848,
-          sizeInBytes: 592,
-          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
-              VMRegion.PROTECTION_FLAG_EXECUTE,
-          mappedFile: '/dev/ashmem/dalvik',
-          byteStats: {
-            privateResident: 205,
-            sharedResident: 0,
-            proportionalResident: 205
-          }
-        })
-      ];
-    });
-    assert.equal(pmd.mostRecentTotalProportionalResidentSizeInBytes, 363);
-    assert.equal(pmd.mostRecentTotalPrivateResidentSizeInBytes, 301);
-    assert.equal(pmd.mostRecentTotalSharedResidentSizeInBytes, 144);
-  });
-
-  test('hookUpMostRecentVmRegionsLinks_emptyArray', function() {
-    var dumps = [];
-    ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(dumps);
-    assert.lengthOf(dumps, 0);
-  });
-
-  test('hookUpMostRecentVmRegionsLinks_nonEmptyArray', function() {
-    var m = new TraceModel();
-
-    // A dump with no VM regions or allocator dumps.
-    var dump1 = createProcessMemoryDump(1, m);
-
-    // A dump with VM regions and malloc and Oilpan allocator dumps.
-    var dump2 = createProcessMemoryDump(2, m);
-    dump2.vmRegions = [];
-    dump2.memoryAllocatorDumps = (function() {
-      var oilpanDump = new MemoryAllocatorDump('oilpan');
-      oilpanDump.addAttribute('outer_size', new ScalarAttribute('bytes', 1024));
-      oilpanDump.addAttribute('objects_count',
-          new ScalarAttribute('objects', 7));
-      oilpanDump.addAttribute('inner_size', new ScalarAttribute('bytes', 768));
-
-      var v8Dump = new MemoryAllocatorDump('v8');
-      v8Dump.addAttribute('outer_size', new ScalarAttribute('bytes', 2048));
-      v8Dump.addAttribute('objects_count', new ScalarAttribute('objects', 15));
-      v8Dump.addAttribute('inner_size', new ScalarAttribute('bytes', 1999));
-
-      return [oilpanDump. v8Dump];
-    })();
-
-    // A dump with malloc and V8 allocator dumps.
-    var dump3 = createProcessMemoryDump(3, m);
-    dump3.memoryAllocatorDumps = (function() {
-      var mallocDump = new MemoryAllocatorDump('malloc');
-      mallocDump.addAttribute('outer_size', new ScalarAttribute('bytes', 1024));
-      mallocDump.addAttribute('objects_count',
-          new ScalarAttribute('objects', 7));
-      mallocDump.addAttribute('inner_size', new ScalarAttribute('bytes', 768));
-
-      var v8Dump = new MemoryAllocatorDump('v8');
-      v8Dump.addAttribute('outer_size', new ScalarAttribute('bytes', 2048));
-      v8Dump.addAttribute('objects_count', new ScalarAttribute('objects', 15));
-      v8Dump.addAttribute('inner_size', new ScalarAttribute('bytes', 1999));
-
-      return [mallocDump. v8Dump];
-    })();
-
-    // A dump with VM regions.
-    var dump4 = createProcessMemoryDump(4, m);
-    dump4.vmRegions = [
-      VMRegion.fromDict({
-        startAddress: 256,
-        sizeInBytes: 336,
-        protectionFlags: VMRegion.PROTECTION_FLAG_READ |
-            VMRegion.PROTECTION_FLAG_WRITE,
-        mappedFile: '[stack:20310]',
-        byteStats: {
-          privateResident: 96,
-          sharedResident: 144,
-          proportionalResident: 158
-        }
-      })
-    ];
-
-    var dumps = [dump1, dump2, dump3, dump4];
-    ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(dumps);
-
-    assert.lengthOf(dumps, 4);
-
-    assert.equal(dumps[0], dump1);
-    assert.isUndefined(dump1.mostRecentVmRegions);
-
-    assert.equal(dumps[1], dump2);
-    assert.equal(dump2.mostRecentVmRegions, dump2.vmRegions_);
-
-    assert.equal(dumps[2], dump3);
-    assert.equal(dump3.mostRecentVmRegions, dump2.vmRegions_);
-
-    assert.equal(dumps[3], dump4);
-    assert.equal(dump4.mostRecentVmRegions, dump4.vmRegions_);
-  });
-
-  test('vmRegion_protectionFlagsToString', function() {
-    checkProtectionFlagsToString(undefined, undefined);
-    checkProtectionFlagsToString(0, '---');
-    checkProtectionFlagsToString(VMRegion.PROTECTION_FLAG_READ, 'r--');
-    checkProtectionFlagsToString(
-        VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_EXECUTE,
-        'r-x');
-    checkProtectionFlagsToString(
-        VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_WRITE,
-        'rw-');
-  });
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/slice.html b/trace-viewer/trace_viewer/core/trace_model/slice.html
deleted file mode 100644
index 3ea1e4f..0000000
--- a/trace-viewer/trace_viewer/core/trace_model/slice.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!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="import" href="/core/trace_model/timed_event.html">
-<link rel="import" href="/core/analysis/util.html">
-
-<script>
-'use strict';
-
-/**
- * @fileoverview Provides the Slice class.
- */
-tv.exportTo('tv.c.trace_model', function() {
-  /**
-   * A Slice represents an interval of time plus parameters associated
-   * with that interval.
-   *
-   * @constructor
-   */
-  function Slice(category, title, colorId, start, args, opt_duration,
-                 opt_cpuStart, opt_cpuDuration) {
-    tv.c.trace_model.TimedEvent.call(this, start);
-
-    this.category = category || '';
-    this.title = title;
-    this.colorId = colorId;
-    this.args = args;
-    this.startStackFrame = undefined;
-    this.endStackFrame = undefined;
-    this.didNotFinish = false;
-    this.inFlowEvents = [];
-    this.outFlowEvents = [];
-    this.subSlices = [];
-    this.selfTime = undefined;
-    this.cpuSelfTime = undefined;
-    this.important = false;
-
-    if (opt_duration !== undefined)
-      this.duration = opt_duration;
-
-    if (opt_cpuStart !== undefined)
-      this.cpuStart = opt_cpuStart;
-
-    if (opt_cpuDuration !== undefined)
-      this.cpuDuration = opt_cpuDuration;
-  }
-
-  Slice.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype,
-
-
-    get analysisTypeName() {
-      return this.title;
-    },
-
-    get userFriendlyName() {
-      return 'Slice ' + this.title + ' at ' +
-          tv.c.analysis.tsString(this.start);
-    },
-
-    findDescendentSlice: function(targetTitle) {
-      if (!this.subSlices)
-        return undefined;
-
-      for (var i = 0; i < this.subSlices.length; i++) {
-        if (this.subSlices[i].title == targetTitle)
-          return this.subSlices[i];
-        var slice = this.subSlices[i].findDescendentSlice(targetTitle);
-        if (slice) return slice;
-      }
-      return undefined;
-    },
-
-    iterateAllDescendents: function(callback, opt_this) {
-      this.subSlices.forEach(callback, opt_this);
-      this.subSlices.forEach(function(subSlice) {
-        subSlice.iterateAllDescendents(callback, opt_this);
-      }, opt_this);
-    }
-  };
-
-  return {
-    Slice: Slice
-  };
-});
-</script>
-
diff --git a/trace-viewer/trace_viewer/core/trace_model/slice_test.html b/trace-viewer/trace_viewer/core/trace_model/slice_test.html
deleted file mode 100644
index 2250512..0000000
--- a/trace-viewer/trace_viewer/core/trace_model/slice_test.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!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="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/slice_group.html">
-
-<script>
-'use strict';
-
-tv.b.unittest.testSuite(function() {
-  var Slice = tv.c.trace_model.Slice;
-  var SliceGroup = tv.c.trace_model.SliceGroup;
-  var newSlice = tv.c.test_utils.newSlice;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-
-  test('findDescendentSlice', function() {
-    var group = new SliceGroup({});
-
-    var sA = group.pushSlice(newSliceNamed('a', 1, 10));
-    var sB = group.pushSlice(newSliceNamed('b', 2, 8));
-    var sC = group.pushSlice(newSliceNamed('c', 3, 6));
-
-    group.createSubSlices();
-
-    assert.equal(sB, sA.findDescendentSlice('b'));
-    assert.equal(sC, sA.findDescendentSlice('c'));
-    assert.isUndefined(sA.findDescendentSlice('d'));
-  });
-
-  test('iterateAllDescendents', function() {
-    var group = new SliceGroup({});
-
-    var sA = group.pushSlice(newSliceNamed('a', 1, 10));
-    var sB = group.pushSlice(newSliceNamed('b', 2, 8));
-    var sC = group.pushSlice(newSliceNamed('c', 3, 6));
-
-    group.createSubSlices();
-
-    var descendentCount = 0;
-    var bCount = 0;
-    var cCount = 0;
-    sA.iterateAllDescendents(function(descendent) {
-      if (descendent == sB)
-        bCount++;
-      if (descendent == sC)
-        cCount++;
-      descendentCount++;
-    });
-
-    assert.equal(bCount, 1);
-    assert.equal(cCount, 1);
-    assert.equal(descendentCount, 2);
-  });
-});
-</script>
diff --git a/trace-viewer/trace_viewer/core/tracks/alert_track.html b/trace-viewer/trace_viewer/core/tracks/alert_track.html
index a16745d..a844e42 100644
--- a/trace-viewer/trace_viewer/core/tracks/alert_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/alert_track.html
@@ -9,20 +9,20 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays an array of alert objects.
    * @constructor
    * @extends {HeadingTrack}
    */
-  var AlertTrack = tv.b.ui.define(
-      'alert-track', tv.c.tracks.LetterDotTrack);
+  var AlertTrack = tr.b.ui.define(
+      'alert-track', tr.c.tracks.LetterDotTrack);
 
   AlertTrack.prototype = {
-    __proto__: tv.c.tracks.LetterDotTrack.prototype,
+    __proto__: tr.c.tracks.LetterDotTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.LetterDotTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.LetterDotTrack.prototype.decorate.call(this, viewport);
       this.heading = 'Alerts';
       this.alerts_ = undefined;
     },
@@ -38,7 +38,7 @@
         return;
       }
       this.items = this.alerts_.map(function(alert) {
-        return new tv.c.tracks.LetterDot(
+        return new tr.c.tracks.LetterDot(
             alert, String.fromCharCode(9888), alert.colorId, alert.start);
       });
     }
diff --git a/trace-viewer/trace_viewer/core/tracks/alert_track_test.html b/trace-viewer/trace_viewer/core/tracks/alert_track_test.html
index e8863af..e1e9c6f 100644
--- a/trace-viewer/trace_viewer/core/tracks/alert_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/alert_track_test.html
@@ -6,32 +6,32 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/global_memory_dump.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/tracks/drawing_container.html">
 <link rel="import" href="/core/tracks/alert_track.html">
+<link rel="import" href="/model/global_memory_dump.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var AlertTrack = tv.c.tracks.AlertTrack;
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Viewport = tv.c.TimelineViewport;
+tr.b.unittest.testSuite(function() {
+  var AlertTrack = tr.c.tracks.AlertTrack;
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
+  var Viewport = tr.c.TimelineViewport;
 
-  var ALERT_INFO_1 = new tv.c.trace_model.EventInfo(
+  var ALERT_INFO_1 = new tr.model.EventInfo(
     'Alert 1', 'One alert');
-  var ALERT_INFO_2 = new tv.c.trace_model.EventInfo(
+  var ALERT_INFO_2 = new tr.model.EventInfo(
     'Alert 2', 'Another alert');
 
   var createAlerts = function() {
     var alerts = [
-      new tv.c.trace_model.Alert(ALERT_INFO_1, 5),
-      new tv.c.trace_model.Alert(ALERT_INFO_1, 20),
-      new tv.c.trace_model.Alert(ALERT_INFO_2, 35),
-      new tv.c.trace_model.Alert(ALERT_INFO_2, 50)
+      new tr.model.Alert(ALERT_INFO_1, 5),
+      new tr.model.Alert(ALERT_INFO_1, 20),
+      new tr.model.Alert(ALERT_INFO_2, 35),
+      new tr.model.Alert(ALERT_INFO_2, 50)
     ];
     return alerts;
   };
@@ -42,7 +42,7 @@
 
     var div = document.createElement('div');
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = AlertTrack(viewport);
@@ -52,7 +52,7 @@
     drawingContainer.invalidate();
 
     track.alerts = alerts;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 50, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
 
diff --git a/trace-viewer/trace_viewer/core/tracks/annotation_view.html b/trace-viewer/trace_viewer/core/tracks/annotation_view.html
index 4f80568..c33f698 100644
--- a/trace-viewer/trace_viewer/core/tracks/annotation_view.html
+++ b/trace-viewer/trace_viewer/core/tracks/annotation_view.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.annotations', function() {
+tr.exportTo('tr.c.annotations', function() {
   /**
    * A base class for all annotation views.
    * @constructor
diff --git a/trace-viewer/trace_viewer/core/tracks/async_slice_group_track.html b/trace-viewer/trace_viewer/core/tracks/async_slice_group_track.html
index 2b50c5a..b0b5b03 100644
--- a/trace-viewer/trace_viewer/core/tracks/async_slice_group_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/async_slice_group_track.html
@@ -12,28 +12,28 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays a AsyncSliceGroup.
    * @constructor
    * @extends {MultiRowTrack}
    */
-  var AsyncSliceGroupTrack = tv.b.ui.define(
+  var AsyncSliceGroupTrack = tr.b.ui.define(
       'async-slice-group-track',
-      tv.c.tracks.MultiRowTrack);
+      tr.c.tracks.MultiRowTrack);
 
   AsyncSliceGroupTrack.prototype = {
 
-    __proto__: tv.c.tracks.MultiRowTrack.prototype,
+    __proto__: tr.c.tracks.MultiRowTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
       this.classList.add('async-slice-group-track');
       this.group_ = undefined;
     },
 
     addSubTrack_: function(slices) {
-      var track = new tv.c.tracks.SliceTrack(this.viewport);
+      var track = new tr.c.tracks.SliceTrack(this.viewport);
       track.slices = slices;
       this.appendChild(track);
       track.asyncStyle = true;
diff --git a/trace-viewer/trace_viewer/core/tracks/async_slice_group_track_test.html b/trace-viewer/trace_viewer/core/tracks/async_slice_group_track_test.html
index 4e752e2..f9ceb9d 100644
--- a/trace-viewer/trace_viewer/core/tracks/async_slice_group_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/async_slice_group_track_test.html
@@ -7,28 +7,28 @@
 
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_track_view.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
-  var AsyncSliceGroup = tv.c.trace_model.AsyncSliceGroup;
-  var AsyncSliceGroupTrack = tv.c.tracks.AsyncSliceGroupTrack;
-  var Process = tv.c.trace_model.Process;
-  var ProcessTrack = tv.c.tracks.ProcessTrack;
-  var Thread = tv.c.trace_model.Thread;
-  var ThreadTrack = tv.c.tracks.ThreadTrack;
-  var newAsyncSlice = tv.c.test_utils.newAsyncSlice;
-  var newAsyncSliceNamed = tv.c.test_utils.newAsyncSliceNamed;
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
+  var AsyncSliceGroup = tr.model.AsyncSliceGroup;
+  var AsyncSliceGroupTrack = tr.c.tracks.AsyncSliceGroupTrack;
+  var Process = tr.model.Process;
+  var ProcessTrack = tr.c.tracks.ProcessTrack;
+  var Thread = tr.model.Thread;
+  var ThreadTrack = tr.c.tracks.ThreadTrack;
+  var newAsyncSlice = tr.c.test_utils.newAsyncSlice;
+  var newAsyncSliceNamed = tr.c.test_utils.newAsyncSliceNamed;
 
   test('filterSubRows', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = new Process(model, 1);
     var t1 = new Thread(p1, 1);
     var g = new AsyncSliceGroup(t1);
     g.push(newAsyncSlice(0, 1, t1, t1));
-    var track = new AsyncSliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new AsyncSliceGroupTrack(new tr.c.TimelineViewport());
     track.group = g;
 
     assert.equal(track.children.length, 1);
@@ -36,7 +36,7 @@
   });
 
   test('rebuildSubRows_twoNonOverlappingSlices', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = new Process(model, 1);
     var t1 = new Thread(p1, 1);
     var g = new AsyncSliceGroup(t1);
@@ -45,7 +45,7 @@
     s1.subSlices = [subs1];
     g.push(s1);
     g.push(newAsyncSlice(1, 1, t1, t1));
-    var track = new AsyncSliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new AsyncSliceGroupTrack(new tr.c.TimelineViewport());
     track.group = g;
     var subRows = track.subRows;
     assert.equal(subRows.length, 2);
@@ -56,7 +56,7 @@
   });
 
   test('rebuildSubRows_twoOverlappingSlices', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = new Process(model, 1);
     var t1 = new Thread(p1, 1);
     var g = new AsyncSliceGroup(t1);
@@ -72,7 +72,7 @@
 
     g.updateBounds();
 
-    var track = new AsyncSliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new AsyncSliceGroupTrack(new tr.c.TimelineViewport());
     track.group = g;
 
     var subRows = track.subRows;
@@ -87,7 +87,7 @@
   });
 
   test('rebuildSubRows_threePartlyOverlappingSlices', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = new Process(model, 1);
     var t1 = new Thread(p1, 1);
     var g = new AsyncSliceGroup(t1);
@@ -95,7 +95,7 @@
     g.push(newAsyncSlice(0, 1.5, t1, t1));
     g.push(newAsyncSlice(1, 1.5, t1, t1));
     g.updateBounds();
-    var track = new AsyncSliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new AsyncSliceGroupTrack(new tr.c.TimelineViewport());
     track.group = g;
     var subRows = track.subRows;
 
@@ -111,7 +111,7 @@
   });
 
   test('rebuildSubRows_threeOverlappingSlices', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = new Process(model, 1);
     var t1 = new Thread(p1, 1);
     var g = new AsyncSliceGroup(t1);
@@ -121,7 +121,7 @@
     g.push(newAsyncSlice(2, 1, t1, t1));
     g.updateBounds();
 
-    var track = new AsyncSliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new AsyncSliceGroupTrack(new tr.c.TimelineViewport());
     track.group = g;
 
     var subRows = track.subRows;
@@ -135,7 +135,7 @@
 
   // Tests that no slices and their sub slices overlap.
   test('rebuildSubRows_NonOverlappingSubSlices', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = new Process(model, 1);
     var t1 = new Thread(p1, 1);
     var g = new AsyncSliceGroup(t1);
@@ -152,7 +152,7 @@
     g.push(slice3);
     g.updateBounds();
 
-    var track = new AsyncSliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new AsyncSliceGroupTrack(new tr.c.TimelineViewport());
     track.group = g;
 
     var subRows = track.subRows;
@@ -168,7 +168,7 @@
   });
 
   test('rebuildSubRows_NonOverlappingSubSlicesThreeNestedLevels', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = new Process(model, 1);
     var t1 = new Thread(p1, 1);
     var g = new AsyncSliceGroup(t1);
@@ -187,7 +187,7 @@
     g.push(slice3);
     g.updateBounds();
 
-    var track = new AsyncSliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new AsyncSliceGroupTrack(new tr.c.TimelineViewport());
     track.group = g;
 
     var subRows = track.subRows;
@@ -203,9 +203,9 @@
   });
 
   test('asyncSliceGroupContainerMap', function() {
-    var vp = new tv.c.TimelineViewport();
+    var vp = new tr.c.TimelineViewport();
     var containerToTrack = vp.containerToTrackObj;
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var process = model.getOrCreateProcess(123);
     var thread = process.getOrCreateThread(456);
     var group = new AsyncSliceGroup(thread);
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_axis.html b/trace-viewer/trace_viewer/core/tracks/chart_axis.html
index 0912abd..cec5e88 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_axis.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_axis.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * A vertical axis for a (set of) chart series which maps an arbitrary range
@@ -19,8 +19,8 @@
    * @constructor
    */
   function ChartAxis(opt_min, opt_max) {
-    this.guid_ = tv.b.GUID.allocate();
-    this.bounds = new tv.b.Range();
+    this.guid_ = tr.b.GUID.allocate();
+    this.bounds = new tr.b.Range();
     if (opt_min !== undefined)
       this.bounds.addValue(opt_min);
     if (opt_max !== undefined)
@@ -49,7 +49,7 @@
      * argument flags.
      */
     autoSetFromSeries: function(series, opt_config) {
-      var range = new tv.b.Range();
+      var range = new tr.b.Range();
       series.forEach(function(s) {
         range.addRange(s.range);
       }, this);
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_axis_test.html b/trace-viewer/trace_viewer/core/tracks/chart_axis_test.html
index ea3a99b..1080b15 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_axis_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_axis_test.html
@@ -14,11 +14,11 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ChartAxis = tv.c.tracks.ChartAxis;
-  var ChartPoint = tv.c.tracks.ChartPoint;
-  var ChartSeries = tv.c.tracks.ChartSeries;
-  var Range = tv.b.Range;
+tr.b.unittest.testSuite(function() {
+  var ChartAxis = tr.c.tracks.ChartAxis;
+  var ChartPoint = tr.c.tracks.ChartPoint;
+  var ChartSeries = tr.c.tracks.ChartSeries;
+  var Range = tr.b.Range;
 
   function buildRange() {
     var range = new Range();
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_point.html b/trace-viewer/trace_viewer/core/tracks/chart_point.html
index 02ba153..6e6c90b 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_point.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_point.html
@@ -5,12 +5,12 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/proxy_selectable_item.html">
+<link rel="import" href="/model/proxy_selectable_item.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * A point in a chart series with x (timestamp) and y (value) coordinates
@@ -22,7 +22,7 @@
    * @extends {ProxySelectableItem}
    */
   function ChartPoint(modelItem, x, y, opt_yBase) {
-    tv.c.trace_model.ProxySelectableItem.call(this, modelItem);
+    tr.model.ProxySelectableItem.call(this, modelItem);
     this.x = x;
     this.y = y;
 
@@ -33,7 +33,7 @@
   };
 
   ChartPoint.prototype = {
-    __proto__: tv.c.trace_model.ProxySelectableItem.prototype
+    __proto__: tr.model.ProxySelectableItem.prototype
   };
 
   return {
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_point_test.html b/trace-viewer/trace_viewer/core/tracks/chart_point_test.html
index 2c89adb..73fe190 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_point_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_point_test.html
@@ -11,8 +11,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ChartPoint = tv.c.tracks.ChartPoint;
+tr.b.unittest.testSuite(function() {
+  var ChartPoint = tr.c.tracks.ChartPoint;
 
   test('checkFields_withoutYBase', function() {
     var event = {};
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_series.html b/trace-viewer/trace_viewer/core/tracks/chart_series.html
index 98bdd12..95127e1 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_series.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_series.html
@@ -7,16 +7,16 @@
 
 <link rel="import" href="/base/range.html">
 <link rel="import" href="/core/event_presenter.html">
-<link rel="import" href="/core/trace_model/proxy_selectable_item.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/proxy_selectable_item.html">
+<link rel="import" href="/model/selection_state.html">
 <link rel="import" href="/core/tracks/heading_track.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
-  var EventPresenter = tv.c.EventPresenter;
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.exportTo('tr.c.tracks', function() {
+  var EventPresenter = tr.c.EventPresenter;
+  var SelectionState = tr.model.SelectionState;
 
   /**
    * The type of a chart series.
@@ -94,7 +94,7 @@
       var config = opt_renderingConfig || {};
 
       // Store all configuration flags as private properties.
-      tv.b.iterItems(DEFAULT_RENDERING_CONFIG, function(key, defaultValue) {
+      tr.b.iterItems(DEFAULT_RENDERING_CONFIG, function(key, defaultValue) {
         var value = config[key];
         if (value === undefined)
           value = defaultValue;
@@ -107,7 +107,7 @@
     },
 
     get range() {
-      var range = new tv.b.Range();
+      var range = new tr.b.Range();
       this.points.forEach(function(point) {
         range.addValue(point.y);
       }, this);
@@ -150,11 +150,11 @@
       var rightTimestamp = transform.rightTimestamp + extraPixels;
 
       // Find the index of the first and last (partially) visible points.
-      var firstVisibleIndex = tv.b.findLowIndexInSortedArray(
+      var firstVisibleIndex = tr.b.findLowIndexInSortedArray(
           this.points,
           function(point) { return point.x; },
           leftTimestamp);
-      var lastVisibleIndex = tv.b.findLowIndexInSortedArray(
+      var lastVisibleIndex = tr.b.findLowIndexInSortedArray(
           this.points,
           function(point) { return point.x; },
           rightTimestamp);
@@ -209,7 +209,7 @@
             break;
           }
           var density = visibleIndexRange / visibleViewXRange;
-          var clampedDensity = tv.b.clamp(density,
+          var clampedDensity = tr.b.clamp(density,
               this.unselectedPointDensityOpaque_,
               this.unselectedPointDensityTransparent_);
           var densityRange = this.unselectedPointDensityTransparent_ -
@@ -442,7 +442,7 @@
         point.addToSelection(selection);
       }
 
-      tv.b.iterateOverIntersectingIntervals(
+      tr.b.iterateOverIntersectingIntervals(
           this.points,
           function(point) { return point.x },
           getPointWidth,
@@ -455,7 +455,7 @@
       if (this.points === undefined)
         return false;
 
-      var index = tv.b.findFirstIndexInArray(this.points, function(point) {
+      var index = tr.b.findFirstIndexInArray(this.points, function(point) {
         return point.modelItem === event;
       }, this);
       if (index === -1)
@@ -474,7 +474,7 @@
       if (this.points === undefined)
         return;
 
-      var item = tv.b.findClosestElementInSortedArray(
+      var item = tr.b.findClosestElementInSortedArray(
           this.points,
           function(point) { return point.x },
           worldX,
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_series_test.html b/trace-viewer/trace_viewer/core/tracks/chart_series_test.html
index 715301a..8e63d47 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_series_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_series_test.html
@@ -8,7 +8,7 @@
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_display_transform.html">
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/model/event.html">
 <link rel="import" href="/core/tracks/chart_axis.html">
 <link rel="import" href="/core/tracks/chart_point.html">
 <link rel="import" href="/core/tracks/chart_series.html">
@@ -17,15 +17,15 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var TimelineDisplayTransform = tv.c.TimelineDisplayTransform;
-  var Event = tv.c.trace_model.Event;
-  var ChartAxis = tv.c.tracks.ChartAxis;
-  var ChartPoint = tv.c.tracks.ChartPoint;
-  var ChartSeries = tv.c.tracks.ChartSeries;
-  var ChartTransform = tv.c.tracks.ChartTransform;
-  var ChartSeriesType = tv.c.tracks.ChartSeriesType;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var TimelineDisplayTransform = tr.c.TimelineDisplayTransform;
+  var Event = tr.model.Event;
+  var ChartAxis = tr.c.tracks.ChartAxis;
+  var ChartPoint = tr.c.tracks.ChartPoint;
+  var ChartSeries = tr.c.tracks.ChartSeries;
+  var ChartTransform = tr.c.tracks.ChartTransform;
+  var ChartSeriesType = tr.c.tracks.ChartSeriesType;
 
   var CANVAS_WIDTH = 800;
   var CANVAS_HEIGHT = 80;
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_track.html b/trace-viewer/trace_viewer/core/tracks/chart_track.html
index 1ff0396..7054604 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_track.html
@@ -19,7 +19,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * A track that displays a chart.
@@ -28,13 +28,13 @@
    * @extends {HeadingTrack}
    */
   var ChartTrack =
-      tv.b.ui.define('chart-track', tv.c.tracks.HeadingTrack);
+      tr.b.ui.define('chart-track', tr.c.tracks.HeadingTrack);
 
   ChartTrack.prototype = {
-    __proto__: tv.c.tracks.HeadingTrack.prototype,
+    __proto__: tr.c.tracks.HeadingTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
       this.classList.add('chart-track');
       this.series_ = undefined;
 
@@ -107,7 +107,7 @@
 
     draw: function(type, viewLWorld, viewRWorld) {
       switch (type) {
-        case tv.c.tracks.DrawType.GENERAL_EVENT:
+        case tr.c.tracks.DrawType.GENERAL_EVENT:
           this.drawChart_(viewLWorld, viewRWorld);
           break;
       }
@@ -141,7 +141,7 @@
 
       // Draw all series in the increasing z-order.
       this.series_.forEach(function(series) {
-        var chartTransform = new tv.c.tracks.ChartTransform(
+        var chartTransform = new tr.c.tracks.ChartTransform(
             displayTransform, series.axis, width, height, topPadding,
             bottomPadding, pixelRatio);
         series.draw(ctx, chartTransform, highDetails);
@@ -198,7 +198,7 @@
      * configuration argument flags.
      */
     autoSetAllAxes: function(opt_config) {
-      tv.b.iterItems(this.axisGuidToAxisData_, function(axisGuid, axisData) {
+      tr.b.iterItems(this.axisGuidToAxisData_, function(axisGuid, axisData) {
         var axis = axisData.axis;
         var series = axisData.series;
         axis.autoSetFromSeries(series, opt_config);
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_track_test.html b/trace-viewer/trace_viewer/core/tracks/chart_track_test.html
index c2dca65..190a805 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_track_test.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_track_view.html">
-<link rel="import" href="/core/trace_model/event.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/event.html">
+<link rel="import" href="/model/selection_state.html">
 <link rel="import" href="/core/tracks/chart_axis.html">
 <link rel="import" href="/core/tracks/chart_point.html">
 <link rel="import" href="/core/tracks/chart_series.html">
@@ -18,16 +18,16 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var Viewport = tv.c.TimelineViewport;
-  var Event = tv.c.trace_model.Event;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var ChartTrack = tv.c.tracks.ChartTrack;
-  var ChartSeries = tv.c.tracks.ChartSeries;
-  var ChartSeriesType = tv.c.tracks.ChartSeriesType;
-  var ChartAxis = tv.c.tracks.ChartAxis;
-  var ChartPoint = tv.c.tracks.ChartPoint;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var Viewport = tr.c.TimelineViewport;
+  var Event = tr.model.Event;
+  var SelectionState = tr.model.SelectionState;
+  var ChartTrack = tr.c.tracks.ChartTrack;
+  var ChartSeries = tr.c.tracks.ChartSeries;
+  var ChartSeriesType = tr.c.tracks.ChartSeriesType;
+  var ChartAxis = tr.c.tracks.ChartAxis;
+  var ChartPoint = tr.c.tracks.ChartPoint;
 
   function buildPoint(x, y) {
     var event = new Event();
@@ -108,7 +108,7 @@
   test('instantiate_lowDetailsWithoutSelection', function() {
     var div = document.createElement('div');
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = buildTrack(viewport);
@@ -117,7 +117,7 @@
     this.addHTMLOutput(div);
     drawingContainer.invalidate();
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     var pixelRatio = window.devicePixelRatio || 1;
     dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
     track.viewport.setDisplayTransformImmediately(dt);
@@ -129,7 +129,7 @@
     var div = document.createElement('div');
     var viewport = new Viewport(div);
     viewport.highDetails = true;
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = buildTrack(viewport);
@@ -145,7 +145,7 @@
     this.addHTMLOutput(div);
     drawingContainer.invalidate();
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     var pixelRatio = window.devicePixelRatio || 1;
     dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
     track.viewport.setDisplayTransformImmediately(dt);
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_transform.html b/trace-viewer/trace_viewer/core/tracks/chart_transform.html
index 6ba29ec..5b1e7c0 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_transform.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_transform.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * A helper object encapsulating all parameters necessary to draw a chart
diff --git a/trace-viewer/trace_viewer/core/tracks/chart_transform_test.html b/trace-viewer/trace_viewer/core/tracks/chart_transform_test.html
index f657eff..7a10651 100644
--- a/trace-viewer/trace_viewer/core/tracks/chart_transform_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/chart_transform_test.html
@@ -13,10 +13,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var TimelineDisplayTransform = tv.c.TimelineDisplayTransform;
-  var ChartTransform = tv.c.tracks.ChartTransform;
-  var ChartAxis = tv.c.tracks.ChartAxis;
+tr.b.unittest.testSuite(function() {
+  var TimelineDisplayTransform = tr.c.TimelineDisplayTransform;
+  var ChartTransform = tr.c.tracks.ChartTransform;
+  var ChartAxis = tr.c.tracks.ChartAxis;
 
   function buildChartTransform() {
     var displayTransform = new TimelineDisplayTransform();
diff --git a/trace-viewer/trace_viewer/core/tracks/comment_box_annotation_view.html b/trace-viewer/trace_viewer/core/tracks/comment_box_annotation_view.html
index 746b6a4..6cdfd2e 100644
--- a/trace-viewer/trace_viewer/core/tracks/comment_box_annotation_view.html
+++ b/trace-viewer/trace_viewer/core/tracks/comment_box_annotation_view.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.annotations', function() {
+tr.exportTo('tr.c.annotations', function() {
   /**
    * A view of a comment box consisting of a textarea and a line to the
    * actual location.
@@ -30,7 +30,7 @@
   }
 
   CommentBoxAnnotationView.prototype = {
-    __proto__: tv.c.annotations.AnnotationView.prototype,
+    __proto__: tr.c.annotations.AnnotationView.prototype,
 
     removeTextArea: function() {
       this.textArea_.parentNode.removeChild(this.textArea_);
@@ -72,7 +72,7 @@
       ctx.strokeStyle = 'rgb(0, 0, 0)';
       ctx.lineWidth = 2;
       ctx.beginPath();
-      tv.c.drawLine(ctx, coords.viewX,
+      tr.c.drawLine(ctx, coords.viewX,
           coords.viewY - ctx.canvas.getBoundingClientRect().top,
           coords.viewX + this.rightOffset,
           coords.viewY - this.topOffset -
diff --git a/trace-viewer/trace_viewer/core/tracks/container_track.html b/trace-viewer/trace_viewer/core/tracks/container_track.html
index 13e18b1..5802aeb 100644
--- a/trace-viewer/trace_viewer/core/tracks/container_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/container_track.html
@@ -13,19 +13,19 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
-  var Task = tv.b.Task;
+tr.exportTo('tr.c.tracks', function() {
+  var Task = tr.b.Task;
 
   /**
    * A generic track that contains other tracks as its children.
    * @constructor
    */
-  var ContainerTrack = tv.b.ui.define('container-track', tv.c.tracks.Track);
+  var ContainerTrack = tr.b.ui.define('container-track', tr.c.tracks.Track);
   ContainerTrack.prototype = {
-    __proto__: tv.c.tracks.Track.prototype,
+    __proto__: tr.c.tracks.Track.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.Track.prototype.decorate.call(this, viewport);
+      tr.c.tracks.Track.prototype.decorate.call(this, viewport);
     },
 
     detach: function() {
@@ -43,7 +43,7 @@
 
     drawTrack: function(type) {
       for (var i = 0; i < this.children.length; ++i) {
-        if (!(this.children[i] instanceof tv.c.tracks.Track))
+        if (!(this.children[i] instanceof tr.c.tracks.Track))
           continue;
         this.children[i].drawTrack(type);
       }
@@ -72,7 +72,7 @@
               loVX, hiVX, loY, hiY, selection);
       }
 
-      tv.c.tracks.Track.prototype.addIntersectingEventsInRangeToSelection.
+      tr.c.tracks.Track.prototype.addIntersectingEventsInRangeToSelection.
           apply(this, arguments);
     },
 
@@ -110,7 +110,7 @@
         }
       }
 
-      tv.c.tracks.Track.prototype.addClosestEventToSelection.
+      tr.c.tracks.Track.prototype.addClosestEventToSelection.
           apply(this, arguments);
     }
   };
diff --git a/trace-viewer/trace_viewer/core/tracks/counter_track.html b/trace-viewer/trace_viewer/core/tracks/counter_track.html
index 677a327..880edf3 100644
--- a/trace-viewer/trace_viewer/core/tracks/counter_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/counter_track.html
@@ -14,7 +14,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * A track that displays a Counter object.
@@ -22,13 +22,13 @@
    * @extends {ChartTrack}
    */
   var CounterTrack =
-      tv.b.ui.define('counter-track', tv.c.tracks.ChartTrack);
+      tr.b.ui.define('counter-track', tr.c.tracks.ChartTrack);
 
   CounterTrack.prototype = {
-    __proto__: tv.c.tracks.ChartTrack.prototype,
+    __proto__: tr.c.tracks.ChartTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ChartTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ChartTrack.prototype.decorate.call(this, viewport);
       this.classList.add('counter-track');
     },
 
@@ -52,19 +52,19 @@
     var totals = counter.totals;
 
     // Create one common axis for all series.
-    var chartAxis = new tv.c.tracks.ChartAxis(0, undefined);
+    var chartAxis = new tr.c.tracks.ChartAxis(0, undefined);
 
     // Build one chart series for each counter series.
     var chartSeries = counter.series.map(function(series, seriesIndex) {
       var chartPoints = series.samples.map(function(sample, sampleIndex) {
         var total = totals[sampleIndex * numSeries + seriesIndex];
-        return new tv.c.tracks.ChartPoint(sample, sample.timestamp, total);
+        return new tr.c.tracks.ChartPoint(sample, sample.timestamp, total);
       });
       var renderingConfig = {
-        chartType: tv.c.tracks.ChartSeriesType.AREA,
+        chartType: tr.c.tracks.ChartSeriesType.AREA,
         colorId: series.color
       };
-      return new tv.c.tracks.ChartSeries(
+      return new tr.c.tracks.ChartSeries(
           chartPoints, chartAxis, renderingConfig);
     });
 
diff --git a/trace-viewer/trace_viewer/core/tracks/counter_track_perf_test.html b/trace-viewer/trace_viewer/core/tracks/counter_track_perf_test.html
index f56115b..de62198 100644
--- a/trace-viewer/trace_viewer/core/tracks/counter_track_perf_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/counter_track_perf_test.html
@@ -6,13 +6,13 @@
 -->
 
 <link rel="import" href="/trace_viewer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/full_config.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function getSynchronous(url) {
     var req = new XMLHttpRequest();
     req.open('GET', url, false);
@@ -43,7 +43,7 @@
         return;
       var fileUrl = '/test_data/counter_tracks.html';
       var events = getSynchronous(fileUrl);
-      model = new tv.c.TraceModel();
+      model = new tr.Model();
       model.importTraces([events], true);
     }
 
@@ -51,12 +51,12 @@
       setUpOnce();
       viewportDiv = document.createElement('div');
 
-      var viewport = new tv.c.TimelineViewport(viewportDiv);
+      var viewport = new tr.c.TimelineViewport(viewportDiv);
 
-      drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+      drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
       viewport.modelTrackContainer = drawingContainer;
 
-      var modelTrack = new tv.c.tracks.TraceModelTrack(viewport);
+      var modelTrack = new tr.c.tracks.ModelTrack(viewport);
       drawingContainer.appendChild(modelTrack);
 
       modelTrack.model = model;
@@ -75,7 +75,7 @@
       worldMid = min + range / 2;
 
       var boost = range * 0.15;
-      var dt = new tv.c.TimelineDisplayTransform();
+      var dt = new tr.c.TimelineDisplayTransform();
       dt.xSetWorldBounds(min - boost, min + range + boost, viewportWidth);
       modelTrack.viewport.setDisplayTransformImmediately(dt);
       startScale = dt.scaleX;
@@ -90,7 +90,7 @@
             for (var j = Math.floor(samples.length / 2); j < samples.length;
                  j++) {
               samples[j].selectionState =
-                  tv.c.trace_model.SelectionState.SELECTED;
+                  tr.model.SelectionState.SELECTED;
             }
           }
         }
diff --git a/trace-viewer/trace_viewer/core/tracks/counter_track_test.html b/trace-viewer/trace_viewer/core/tracks/counter_track_test.html
index 23d7bbc..36b2713 100644
--- a/trace-viewer/trace_viewer/core/tracks/counter_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/counter_track_test.html
@@ -11,10 +11,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Counter = tv.c.trace_model.Counter;
-  var Viewport = tv.c.TimelineViewport;
-  var CounterTrack = tv.c.tracks.CounterTrack;
+tr.b.unittest.testSuite(function() {
+  var Counter = tr.model.Counter;
+  var Viewport = tr.c.TimelineViewport;
+  var CounterTrack = tr.c.tracks.CounterTrack;
 
   var runTest = function(timestamps, samples, testFn) {
     var testEl = document.createElement('div');
@@ -23,8 +23,8 @@
     var n = samples.length;
 
     for (var i = 0; i < n; ++i) {
-      ctr.addSeries(new tv.c.trace_model.CounterSeries('value' + i,
-          tv.b.ui.getColorIdForGeneralPurposeString('value' + i)));
+      ctr.addSeries(new tr.model.CounterSeries('value' + i,
+          tr.b.ui.getColorIdForGeneralPurposeString('value' + i)));
     }
 
     for (var i = 0; i < samples.length; ++i) {
@@ -37,7 +37,7 @@
 
     var viewport = new Viewport(testEl);
 
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     testEl.appendChild(drawingContainer);
 
     var track = new CounterTrack(viewport);
@@ -53,7 +53,7 @@
 
     track.heading = ctr.name;
     track.counter = ctr;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 10, track.clientWidth * pixelRatio);
     track.viewport.setDisplayTransformImmediately(dt);
 
@@ -63,10 +63,10 @@
   test('instantiate', function() {
     var ctr = new Counter(undefined, 'testBasicCounter', '',
         'testBasicCounter');
-    ctr.addSeries(new tv.c.trace_model.CounterSeries('value1',
-        tv.b.ui.getColorIdForGeneralPurposeString('testBasicCounter.value1')));
-    ctr.addSeries(new tv.c.trace_model.CounterSeries('value2',
-        tv.b.ui.getColorIdForGeneralPurposeString('testBasicCounter.value2')));
+    ctr.addSeries(new tr.model.CounterSeries('value1',
+        tr.b.ui.getColorIdForGeneralPurposeString('testBasicCounter.value1')));
+    ctr.addSeries(new tr.model.CounterSeries('value2',
+        tr.b.ui.getColorIdForGeneralPurposeString('testBasicCounter.value2')));
 
     var timestamps = [0, 1, 2, 3, 4, 5, 6, 7];
     var samples = [[0, 3, 1, 2, 3, 1, 3, 3.1],
@@ -82,7 +82,7 @@
     var div = document.createElement('div');
     var viewport = new Viewport(div);
 
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = new CounterTrack(viewport);
@@ -93,7 +93,7 @@
 
     track.heading = ctr.name;
     track.counter = ctr;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 7.7, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
@@ -108,7 +108,7 @@
       var y75 = clientRect.top + (0.75 * clientRect.height);
 
       // In bounds.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       var x = 0.15 * clientRect.width;
       track.addIntersectingEventsInRangeToSelection(
           x, x + 1, y75, y75 + 1, sel);
@@ -123,13 +123,13 @@
       assert.equal(sel[1].series.seriesIndex, 0);
 
       // Outside bounds.
-      sel = new tv.c.Selection();
+      sel = new tr.c.Selection();
       var x = -0.5 * clientRect.width;
       track.addIntersectingEventsInRangeToSelection(
           x, x + 1, y75, y75 + 1, sel);
       assert.equal(sel.length, 0);
 
-      sel = new tv.c.Selection();
+      sel = new tr.c.Selection();
       var x = 0.8 * clientRect.width;
       track.addIntersectingEventsInRangeToSelection(
           x, x + 1, y75, y75 + 1, sel);
@@ -144,43 +144,43 @@
 
     runTest.call(this, timestamps, samples, function(ctr, container, track) {
       // Before with not range.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(-1, 0, 0, 0, sel);
       assert.equal(sel.length, 0);
 
       // Before with negative range.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(-1, -10, 0, 0, sel);
       assert.equal(sel.length, 0);
 
       // Before first sample.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(-1, 1, 0, 0, sel);
       assert.equal(sel.length, 2);
       assert.equal(sel[0].getSampleIndex(), 0);
 
       // Between and closer to sample before.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(1.3, 1, 0, 0, sel);
       assert.equal(sel[0].getSampleIndex(), 1);
 
       // Between samples with bad range.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(1.45, 0.25, 0, 0, sel);
       assert.equal(sel.length, 0);
 
       // Between and closer to next sample.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(4.7, 6, 0, 0, sel);
       assert.equal(sel[0].getSampleIndex(), 5);
 
       // After last sample with good range.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(8.5, 2, 0, 0, sel);
       assert.equal(sel[0].getSampleIndex(), 7);
 
       // After last sample with bad range.
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       track.addClosestEventToSelection(10, 1, 0, 0, sel);
       assert.equal(sel.length, 0);
     });
diff --git a/trace-viewer/trace_viewer/core/tracks/cpu_track.html b/trace-viewer/trace_viewer/core/tracks/cpu_track.html
index 0b9ef8b..b07f204 100644
--- a/trace-viewer/trace_viewer/core/tracks/cpu_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/cpu_track.html
@@ -8,25 +8,25 @@
 <link rel="import" href="/core/tracks/container_track.html">
 <link rel="import" href="/core/tracks/slice_track.html">
 <link rel="import" href="/core/filter.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/base/ui.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * Visualizes a Cpu using a series of of SliceTracks.
    * @constructor
    */
   var CpuTrack =
-      tv.b.ui.define('cpu-track', tv.c.tracks.ContainerTrack);
+      tr.b.ui.define('cpu-track', tr.c.tracks.ContainerTrack);
   CpuTrack.prototype = {
-    __proto__: tv.c.tracks.ContainerTrack.prototype,
+    __proto__: tr.c.tracks.ContainerTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
       this.classList.add('cpu-track');
       this.detailedMode_ = true;
     },
@@ -66,7 +66,7 @@
         return true;
       if (cpu.samples && cpu.samples.length)
         return true;
-      if (tv.b.dictionaryLength(cpu.counters) > 0)
+      if (tr.b.dictionaryLength(cpu.counters) > 0)
         return true;
       return false;
     },
@@ -77,7 +77,7 @@
         return;
       var slices = this.cpu_.slices;
       if (slices.length) {
-        var track = new tv.c.tracks.SliceTrack(this.viewport);
+        var track = new tr.c.tracks.SliceTrack(this.viewport);
         track.slices = slices;
         track.heading = this.cpu_.userFriendlyName + ':';
         this.appendChild(track);
@@ -88,7 +88,7 @@
 
         for (var counterName in this.cpu_.counters) {
           var counter = this.cpu_.counters[counterName];
-          track = new tv.c.tracks.CounterTrack(this.viewport);
+          track = new tr.c.tracks.CounterTrack(this.viewport);
           track.heading = this.cpu_.userFriendlyName + ' ' +
               counter.name + ':';
           track.counter = counter;
@@ -108,19 +108,19 @@
         samplesByTitle[sample.title].push(sample);
       });
 
-      var sampleTitles = tv.b.dictionaryKeys(samplesByTitle);
+      var sampleTitles = tr.b.dictionaryKeys(samplesByTitle);
       sampleTitles.sort();
 
       sampleTitles.forEach(function(sampleTitle) {
         var samples = samplesByTitle[sampleTitle];
-        var samplesTrack = new tv.c.tracks.SliceTrack(this.viewport);
+        var samplesTrack = new tr.c.tracks.SliceTrack(this.viewport);
         samplesTrack.group = this.cpu_;
         samplesTrack.slices = samples;
         samplesTrack.heading = this.cpu_.userFriendlyName + ': ' +
             sampleTitle;
         samplesTrack.tooltip = this.cpu_.userFriendlyDetails;
         samplesTrack.selectionGenerator = function() {
-          var selection = new tv.c.Selection();
+          var selection = new tr.c.Selection();
           for (var i = 0; i < samplesTrack.slices.length; i++) {
             selection.push(samplesTrack.slices[i]);
           }
diff --git a/trace-viewer/trace_viewer/core/tracks/cpu_track_test.html b/trace-viewer/trace_viewer/core/tracks/cpu_track_test.html
index 8ddf336..4ba9428 100644
--- a/trace-viewer/trace_viewer/core/tracks/cpu_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/cpu_track_test.html
@@ -7,19 +7,19 @@
 
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_track_view.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Cpu = tv.c.trace_model.Cpu;
-  var CpuTrack = tv.c.tracks.CpuTrack;
-  var Slice = tv.c.trace_model.Slice;
-  var StackFrame = tv.c.trace_model.StackFrame;
-  var Sample = tv.c.trace_model.Sample;
-  var Thread = tv.c.trace_model.Thread;
-  var Viewport = tv.c.TimelineViewport;
+tr.b.unittest.testSuite(function() {
+  var Cpu = tr.model.Cpu;
+  var CpuTrack = tr.c.tracks.CpuTrack;
+  var Slice = tr.model.Slice;
+  var StackFrame = tr.model.StackFrame;
+  var Sample = tr.model.Sample;
+  var Thread = tr.model.Thread;
+  var Viewport = tr.c.TimelineViewport;
 
   test('basicCpu', function() {
     var cpu = new Cpu({}, 7);
@@ -32,21 +32,21 @@
     var testEl = document.createElement('div');
     var viewport = new Viewport(testEl);
 
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
 
     var track = new CpuTrack(viewport);
     drawingContainer.appendChild(track);
 
     track.heading = 'CPU ' + cpu.cpuNumber;
     track.cpu = cpu;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 11.1, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
 
 
   test('withSamples', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var thread;
     var cpu;
     model.importTraces([], false, false, function() {
@@ -80,14 +80,14 @@
     var testEl = document.createElement('div');
     var viewport = new Viewport(testEl);
 
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
 
     var track = new CpuTrack(viewport);
     drawingContainer.appendChild(track);
 
     track.heading = 'CPU ' + cpu.cpuNumber;
     track.cpu = cpu;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 11.1, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
diff --git a/trace-viewer/trace_viewer/core/tracks/drawing_container.html b/trace-viewer/trace_viewer/core/tracks/drawing_container.html
index 3081d75..e5f50ed 100644
--- a/trace-viewer/trace_viewer/core/tracks/drawing_container.html
+++ b/trace-viewer/trace_viewer/core/tracks/drawing_container.html
@@ -14,7 +14,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   var DrawType = {
     GENERAL_EVENT: 1,
     INSTANT_EVENT: 2,
@@ -26,19 +26,19 @@
     ANNOTATIONS: 8
   };
 
-  var DrawingContainer = tv.b.ui.define('drawing-container',
-                                        tv.c.tracks.Track);
+  var DrawingContainer = tr.b.ui.define('drawing-container',
+                                        tr.c.tracks.Track);
 
   DrawingContainer.prototype = {
-    __proto__: tv.c.tracks.Track.prototype,
+    __proto__: tr.c.tracks.Track.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.Track.prototype.decorate.call(this, viewport);
+      tr.c.tracks.Track.prototype.decorate.call(this, viewport);
       this.classList.add('drawing-container');
 
       this.canvas_ = document.createElement('canvas');
       this.canvas_.className = 'drawing-container-canvas';
-      this.canvas_.style.left = tv.c.constants.HEADING_WIDTH + 'px';
+      this.canvas_.style.left = tr.c.constants.HEADING_WIDTH + 'px';
       this.appendChild(this.canvas_);
 
       this.ctx_ = this.canvas_.getContext('2d');
@@ -65,14 +65,14 @@
         return;
       this.rafPending_ = true;
 
-      tv.b.requestPreAnimationFrame(this.preDraw_, this);
+      tr.b.requestPreAnimationFrame(this.preDraw_, this);
     },
 
     preDraw_: function() {
       this.rafPending_ = false;
       this.updateCanvasSizeIfNeeded_();
 
-      tv.b.requestAnimationFrameInThisFrameIfPossible(this.draw_, this);
+      tr.b.requestAnimationFrameInThisFrameIfPossible(this.draw_, this);
     },
 
     draw_: function() {
@@ -85,15 +85,13 @@
         DrawType.INSTANT_EVENT,
         DrawType.GENERAL_EVENT,
         DrawType.MARKERS,
-        DrawType.ANNOTATIONS
+        DrawType.ANNOTATIONS,
+        DrawType.FLOW_ARROWS
       ];
 
-      if (this.viewport.showFlowEvents)
-        typesToDraw.push(DrawType.FLOW_ARROWS);
-
       for (var idx in typesToDraw) {
         for (var i = 0; i < this.children.length; ++i) {
-          if (!(this.children[i] instanceof tv.c.tracks.Track))
+          if (!(this.children[i] instanceof tr.c.tracks.Track))
             continue;
           this.children[i].drawTrack(typesToDraw[idx]);
         }
@@ -111,7 +109,7 @@
 
     updateCanvasSizeIfNeeded_: function() {
       var visibleChildTracks =
-          tv.b.asArray(this.children).filter(this.visibleFilter_);
+          tr.b.asArray(this.children).filter(this.visibleFilter_);
 
       var thisBounds = this.getBoundingClientRect();
 
@@ -121,7 +119,7 @@
               getBoundingClientRect();
 
       var innerWidth = firstChildTrackBounds.width -
-          tv.c.constants.HEADING_WIDTH;
+          tr.c.constants.HEADING_WIDTH;
       var innerHeight = lastChildTrackBounds.bottom - firstChildTrackBounds.top;
 
       var pixelRatio = window.devicePixelRatio || 1;
@@ -137,7 +135,7 @@
     },
 
     visibleFilter_: function(element) {
-      if (!(element instanceof tv.c.tracks.Track))
+      if (!(element instanceof tr.c.tracks.Track))
         return false;
       return window.getComputedStyle(element).display !== 'none';
     },
@@ -145,7 +143,7 @@
     addClosestEventToSelection: function(
         worldX, worldMaxDist, loY, hiY, selection) {
       for (var i = 0; i < this.children.length; ++i) {
-        if (!(this.children[i] instanceof tv.c.tracks.Track))
+        if (!(this.children[i] instanceof tr.c.tracks.Track))
           continue;
         var trackClientRect = this.children[i].getBoundingClientRect();
         var a = Math.max(loY, trackClientRect.top);
@@ -156,13 +154,13 @@
         }
       }
 
-      tv.c.tracks.Track.prototype.addClosestEventToSelection.
+      tr.c.tracks.Track.prototype.addClosestEventToSelection.
           apply(this, arguments);
     },
 
     addEventsToTrackMap: function(eventToTrackMap) {
       for (var i = 0; i < this.children.length; ++i) {
-        if (!(this.children[i] instanceof tv.c.tracks.Track))
+        if (!(this.children[i] instanceof tr.c.tracks.Track))
           continue;
         this.children[i].addEventsToTrackMap(eventToTrackMap);
       }
@@ -170,7 +168,7 @@
 
     addContainersToTrackMap: function(containerToTrackMap) {
       for (var i = 0; i < this.children.length; ++i) {
-        if (!(this.children[i] instanceof tv.c.tracks.Track))
+        if (!(this.children[i] instanceof tr.c.tracks.Track))
           continue;
         this.children[i].addContainersToTrackMap(containerToTrackMap);
       }
diff --git a/trace-viewer/trace_viewer/core/tracks/drawing_container_perf_test.html b/trace-viewer/trace_viewer/core/tracks/drawing_container_perf_test.html
index 2ceeffc..b956e97 100644
--- a/trace-viewer/trace_viewer/core/tracks/drawing_container_perf_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/drawing_container_perf_test.html
@@ -6,43 +6,43 @@
 -->
 
 <link rel="import" href="/base/xhr.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/extras/full_config.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {  // @suppress longLineCheck
+tr.b.unittest.testSuite(function() {  // @suppress longLineCheck
   var generalModel;
   function getOrCreateGeneralModel() {
     if (generalModel !== undefined)
       generalModel;
     var fileUrl = '/test_data/thread_time_visualisation.json.gz';
-    var events = tv.b.getSync(fileUrl);
-    generalModel = new tv.c.TraceModel();
+    var events = tr.b.getSync(fileUrl);
+    generalModel = new tr.Model();
     generalModel.importTraces([events], true);
     return generalModel;
   }
 
   function DCPerfTestCase(testName, opt_options) {
-    tv.b.unittest.PerfTestCase.call(this, testName, undefined, opt_options);
+    tr.b.unittest.PerfTestCase.call(this, testName, undefined, opt_options);
     this.viewportDiv = undefined;
     this.drawingContainer = undefined;
     this.viewport = undefined;
   }
   DCPerfTestCase.prototype = {
-    __proto__: tv.b.unittest.PerfTestCase.prototype,
+    __proto__: tr.b.unittest.PerfTestCase.prototype,
 
     setUp: function(model) {
       this.viewportDiv = document.createElement('div');
 
-      this.viewport = new tv.c.TimelineViewport(this.viewportDiv);
+      this.viewport = new tr.c.TimelineViewport(this.viewportDiv);
 
-      this.drawingContainer = new tv.c.tracks.DrawingContainer(this.viewport);
+      this.drawingContainer = new tr.c.tracks.DrawingContainer(this.viewport);
       this.viewport.modelTrackContainer = this.drawingContainer;
 
-      var modelTrack = new tv.c.tracks.TraceModelTrack(this.viewport);
+      var modelTrack = new tr.c.tracks.ModelTrack(this.viewport);
       this.drawingContainer.appendChild(modelTrack);
 
       modelTrack.model = model;
@@ -60,7 +60,7 @@
       var range = model.bounds.range;
 
       var boost = range * 0.15;
-      var dt = new tv.c.TimelineDisplayTransform();
+      var dt = new tr.c.TimelineDisplayTransform();
       dt.xSetWorldBounds(min - boost, min + range + boost, w);
       this.viewport.setDisplayTransformImmediately(dt);
     },
@@ -103,16 +103,16 @@
     __proto__: DCPerfTestCase.prototype,
 
     setUp: function() {
-      var model = tv.c.test_utils.newModel(function(m) {
+      var model = tr.c.test_utils.newModel(function(m) {
         var proc = m.getOrCreateProcess(1);
         for (var tid = 1; tid <= 5; tid++) {
           var thread = proc.getOrCreateThread(tid);
           for (var i = 0; i < 5000; i++) {
             var mod = Math.floor(i / 100) % 4;
-            var slice = tv.c.test_utils.newAsyncSliceEx({
+            var slice = tr.c.test_utils.newAsyncSliceEx({
               name: 'Test' + i,
               colorId: tid + mod,
-              id: tv.b.GUID.allocate(),
+              id: tr.b.GUID.allocate(),
               start: i * 10,
               duration: 9,
               isTopLevel: true
@@ -125,7 +125,7 @@
 
       var w = this.drawingContainer.canvas.width;
 
-      var dt = new tv.c.TimelineDisplayTransform();
+      var dt = new tr.c.TimelineDisplayTransform();
       dt.xSetWorldBounds(-2000, 54000, w);
       this.viewport.setDisplayTransformImmediately(dt);
     }
diff --git a/trace-viewer/trace_viewer/core/tracks/frame_track.html b/trace-viewer/trace_viewer/core/tracks/frame_track.html
index 76e1e7c..2a7ae72 100644
--- a/trace-viewer/trace_viewer/core/tracks/frame_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/frame_track.html
@@ -13,8 +13,8 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
-  var palette = tv.b.ui.getColorPalette();
+tr.exportTo('tr.c.tracks', function() {
+  var palette = tr.b.ui.getColorPalette();
 
   var startCompare = function(x, y) { return x.start - y.start; }
 
@@ -22,14 +22,14 @@
    * Track enabling quick selection of frame slices/events.
    * @constructor
    */
-  var FrameTrack = tv.b.ui.define(
-      'frame-track', tv.c.tracks.LetterDotTrack);
+  var FrameTrack = tr.b.ui.define(
+      'frame-track', tr.c.tracks.LetterDotTrack);
 
   FrameTrack.prototype = {
-    __proto__: tv.c.tracks.LetterDotTrack.prototype,
+    __proto__: tr.c.tracks.LetterDotTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.LetterDotTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.LetterDotTrack.prototype.decorate.call(this, viewport);
       this.heading = 'Frames';
 
       this.frames_ = undefined;
@@ -60,11 +60,11 @@
    * @extends {LetterDot}
    */
   function FrameDot(frame) {
-    tv.c.tracks.LetterDot.call(this, frame, 'F', frame.colorId, frame.start);
+    tr.c.tracks.LetterDot.call(this, frame, 'F', frame.colorId, frame.start);
   }
 
   FrameDot.prototype = {
-    __proto__: tv.c.tracks.LetterDot.prototype
+    __proto__: tr.c.tracks.LetterDot.prototype
   };
 
   return {
diff --git a/trace-viewer/trace_viewer/core/tracks/frame_track_test.html b/trace-viewer/trace_viewer/core/tracks/frame_track_test.html
index fc64465..22bcb70 100644
--- a/trace-viewer/trace_viewer/core/tracks/frame_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/frame_track_test.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/frame.html">
+<link rel="import" href="/model/frame.html">
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/tracks/drawing_container.html">
 <link rel="import" href="/core/tracks/frame_track.html">
@@ -14,18 +14,18 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Frame = tv.c.trace_model.Frame;
-  var FrameTrack = tv.c.tracks.FrameTrack;
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Viewport = tv.c.TimelineViewport;
+tr.b.unittest.testSuite(function() {
+  var Frame = tr.model.Frame;
+  var FrameTrack = tr.c.tracks.FrameTrack;
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
+  var Viewport = tr.c.TimelineViewport;
 
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
 
   var createFrames = function() {
     var frames = undefined;
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       var process = model.getOrCreateProcess(1);
       var thread = process.getOrCreateThread(1);
       for (var i = 1; i < 5; i++) {
@@ -47,7 +47,7 @@
 
     var div = document.createElement('div');
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = FrameTrack(viewport);
@@ -57,7 +57,7 @@
     drawingContainer.invalidate();
 
     track.frames = frames;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 50, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
 
diff --git a/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track.html b/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track.html
index b09a90c..0c94709 100644
--- a/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track.html
@@ -13,7 +13,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   var USED_MEMORY_TRACK_HEIGHT = 50;
   var ALLOCATED_MEMORY_TRACK_HEIGHT = 50;
@@ -23,14 +23,14 @@
    * @constructor
    * @extends {ContainerTrack}
    */
-  var GlobalMemoryDumpTrack = tv.b.ui.define(
-      'global-memory-dump-track', tv.c.tracks.ContainerTrack);
+  var GlobalMemoryDumpTrack = tr.b.ui.define(
+      'global-memory-dump-track', tr.c.tracks.ContainerTrack);
 
   GlobalMemoryDumpTrack.prototype = {
-    __proto__: tv.c.tracks.ContainerTrack.prototype,
+    __proto__: tr.c.tracks.ContainerTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
       this.memoryDumps_ = undefined;
     },
 
@@ -58,23 +58,23 @@
     },
 
     appendDumpDotsTrack_: function() {
-      var items = tv.c.tracks.buildMemoryLetterDots(this.memoryDumps_);
+      var items = tr.c.tracks.buildMemoryLetterDots(this.memoryDumps_);
       if (!items)
         return;
 
-      var track = new tv.c.tracks.LetterDotTrack(this.viewport);
+      var track = new tr.c.tracks.LetterDotTrack(this.viewport);
       track.heading = 'Memory Dumps';
       track.items = items;
       this.appendChild(track);
     },
 
     appendUsedMemoryTrack_: function() {
-      var series = tv.c.tracks.buildGlobalUsedMemoryChartSeries(
+      var series = tr.c.tracks.buildGlobalUsedMemoryChartSeries(
           this.memoryDumps_);
       if (!series)
         return;
 
-      var track = new tv.c.tracks.ChartTrack(this.viewport);
+      var track = new tr.c.tracks.ChartTrack(this.viewport);
       track.heading = 'Used memory (per process)';
       track.height = USED_MEMORY_TRACK_HEIGHT + 'px';
       track.series = series;
@@ -83,12 +83,12 @@
     },
 
     appendAllocatedMemoryTrack_: function() {
-      var series = tv.c.tracks.buildGlobalAllocatedMemoryChartSeries(
+      var series = tr.c.tracks.buildGlobalAllocatedMemoryChartSeries(
           this.memoryDumps_);
       if (!series)
         return;
 
-      var track = new tv.c.tracks.ChartTrack(this.viewport);
+      var track = new tr.c.tracks.ChartTrack(this.viewport);
       track.heading = 'Allocated memory (per allocator)';
       track.height = ALLOCATED_MEMORY_TRACK_HEIGHT + 'px';
       track.series = series;
diff --git a/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track_test.html b/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track_test.html
index 3cd4c28..59b9452 100644
--- a/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/global_memory_dump_track_test.html
@@ -14,10 +14,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Viewport = tv.c.TimelineViewport;
-  var GlobalMemoryDumpTrack = tv.c.tracks.GlobalMemoryDumpTrack;
-  var createTestGlobalMemoryDumps = tv.c.tracks.createTestGlobalMemoryDumps;
+tr.b.unittest.testSuite(function() {
+  var Viewport = tr.c.TimelineViewport;
+  var GlobalMemoryDumpTrack = tr.c.tracks.GlobalMemoryDumpTrack;
+  var createTestGlobalMemoryDumps = tr.c.tracks.createTestGlobalMemoryDumps;
 
   function instantiateTrack(withVMRegions, withAllocatorDumps,
                             expectedTrackCount) {
@@ -25,7 +25,7 @@
 
     var div = document.createElement('div');
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = new GlobalMemoryDumpTrack(viewport);
@@ -35,7 +35,7 @@
     track.memoryDumps = dumps;
     this.addHTMLOutput(div);
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 50, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
 
diff --git a/trace-viewer/trace_viewer/core/tracks/heading_track.html b/trace-viewer/trace_viewer/core/tracks/heading_track.html
index 15a88c4..37a74ca 100644
--- a/trace-viewer/trace_viewer/core/tracks/heading_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/heading_track.html
@@ -15,7 +15,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   var DOWN_ARROW = String.fromCharCode(0x25BE);
   var RIGHT_ARROW = String.fromCharCode(0x25B8);
 
@@ -25,17 +25,17 @@
    * @constructor
    * @extends {HTMLDivElement}
    */
-  var HeadingTrack = tv.b.ui.define('heading-track', tv.c.tracks.Track);
+  var HeadingTrack = tr.b.ui.define('heading-track', tr.c.tracks.Track);
 
   HeadingTrack.prototype = {
-    __proto__: tv.c.tracks.Track.prototype,
+    __proto__: tr.c.tracks.Track.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.Track.prototype.decorate.call(this, viewport);
+      tr.c.tracks.Track.prototype.decorate.call(this, viewport);
       this.classList.add('heading-track');
 
       this.headingDiv_ = document.createElement('heading');
-      this.headingDiv_.style.width = tv.c.constants.HEADING_WIDTH + 'px';
+      this.headingDiv_.style.width = tr.c.constants.HEADING_WIDTH + 'px';
       this.headingDiv_.addEventListener(
           'click', this.onHeadingDivClicked_.bind(this));
       this.heading_ = '';
@@ -79,7 +79,7 @@
     },
 
     onHeadingDivClicked_: function() {
-      var e = new Event('heading-clicked', true, false);
+      var e = new Event('heading-clicked', {'bubbles': true});
       this.dispatchEvent(e);
     },
 
@@ -106,7 +106,7 @@
       this.headingDiv_.appendChild(span);
 
       if (this.selectionGenerator_) {
-        this.headingLink_ = document.createElement('tv-c-analysis-link');
+        this.headingLink_ = document.createElement('tr-c-a-analysis-link');
         this.headingLink_.selection = this.selectionGenerator_;
         this.headingLink_.textContent = '';
         this.headingDiv_.appendChild(this.headingLink_);
diff --git a/trace-viewer/trace_viewer/core/tracks/highlighter.html b/trace-viewer/trace_viewer/core/tracks/highlighter.html
index 50d8eee..e7767f5 100644
--- a/trace-viewer/trace_viewer/core/tracks/highlighter.html
+++ b/trace-viewer/trace_viewer/core/tracks/highlighter.html
@@ -14,7 +14,7 @@
 /**
  * @fileoverview Allows custom highlighting to be added to the full model track.
  */
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * Highlights cetrain features of the model.
@@ -40,10 +40,10 @@
   };
 
 
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
   options.defaultMetadata = {};
   options.mandatoryBaseClass = Highlighter;
-  tv.b.decorateExtensionRegistry(Highlighter, options);
+  tr.b.decorateExtensionRegistry(Highlighter, options);
 
   return {
     Highlighter: Highlighter
diff --git a/trace-viewer/trace_viewer/core/tracks/kernel_track.html b/trace-viewer/trace_viewer/core/tracks/kernel_track.html
index 1a0617c..22286f7 100644
--- a/trace-viewer/trace_viewer/core/tracks/kernel_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/kernel_track.html
@@ -12,22 +12,22 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
-  var Cpu = tv.c.trace_model.Cpu;
-  var CpuTrack = tv.c.tracks.cpu_track;
-  var ProcessTrackBase = tv.c.tracks.ProcessTrackBase;
-  var SpacingTrack = tv.c.tracks.SpacingTrack;
+tr.exportTo('tr.c.tracks', function() {
+  var Cpu = tr.model.Cpu;
+  var CpuTrack = tr.c.tracks.cpu_track;
+  var ProcessTrackBase = tr.c.tracks.ProcessTrackBase;
+  var SpacingTrack = tr.c.tracks.SpacingTrack;
 
   /**
    * @constructor
    */
-  var KernelTrack = tv.b.ui.define('kernel-track', ProcessTrackBase);
+  var KernelTrack = tr.b.ui.define('kernel-track', ProcessTrackBase);
 
   KernelTrack.prototype = {
     __proto__: ProcessTrackBase.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ProcessTrackBase.prototype.decorate.call(this, viewport);
+      ProcessTrackBase.prototype.decorate.call(this, viewport);
     },
 
 
@@ -53,13 +53,13 @@
     },
 
     willAppendTracks_: function() {
-      var cpus = tv.b.dictionaryValues(this.kernel.cpus);
-      cpus.sort(tv.c.trace_model.Cpu.compare);
+      var cpus = tr.b.dictionaryValues(this.kernel.cpus);
+      cpus.sort(tr.model.Cpu.compare);
 
       var didAppendAtLeastOneTrack = false;
       for (var i = 0; i < cpus.length; ++i) {
         var cpu = cpus[i];
-        var track = new tv.c.tracks.CpuTrack(this.viewport);
+        var track = new tr.c.tracks.CpuTrack(this.viewport);
         track.detailedMode = this.expanded;
         track.cpu = cpu;
         if (!track.hasVisibleContent)
diff --git a/trace-viewer/trace_viewer/core/tracks/letter_dot_track.html b/trace-viewer/trace_viewer/core/tracks/letter_dot_track.html
index 56f65d5..8aefc8d 100644
--- a/trace-viewer/trace_viewer/core/tracks/letter_dot_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/letter_dot_track.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/core/event_presenter.html">
-<link rel="import" href="/core/trace_model/proxy_selectable_item.html">
+<link rel="import" href="/model/proxy_selectable_item.html">
 <link rel="import" href="/core/tracks/heading_track.html">
 <link rel="import" href="/base/ui/color_scheme.html">
 <link rel="import" href="/base/sorted_array_utils.html">
@@ -20,23 +20,23 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
-  var EventPresenter = tv.c.EventPresenter;
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.exportTo('tr.c.tracks', function() {
+  var EventPresenter = tr.c.EventPresenter;
+  var SelectionState = tr.model.SelectionState;
 
   /**
    * A track that displays an array of dots with filled letters inside them.
    * @constructor
    * @extends {HeadingTrack}
    */
-  var LetterDotTrack = tv.b.ui.define(
-      'letter-dot-track', tv.c.tracks.HeadingTrack);
+  var LetterDotTrack = tr.b.ui.define(
+      'letter-dot-track', tr.c.tracks.HeadingTrack);
 
   LetterDotTrack.prototype = {
-    __proto__: tv.c.tracks.HeadingTrack.prototype,
+    __proto__: tr.c.tracks.HeadingTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
       this.classList.add('letter-dot-track');
       this.items_ = undefined;
     },
@@ -66,7 +66,7 @@
       if (this.items_ === undefined)
         return;
       switch (type) {
-        case tv.c.tracks.DrawType.GENERAL_EVENT:
+        case tr.c.tracks.DrawType.GENERAL_EVENT:
           this.drawLetterDots_(viewLWorld, viewRWorld);
           break;
       }
@@ -80,8 +80,8 @@
       var height = bounds.height * pixelRatio;
       var halfHeight = height * 0.5;
       var twoPi = Math.PI * 2;
-      var palette = tv.b.ui.getColorPalette();
-      var highlightIdBoost = tv.b.ui.paletteProperties.highlightIdBoost;
+      var palette = tr.b.ui.getColorPalette();
+      var highlightIdBoost = tr.b.ui.paletteProperties.highlightIdBoost;
 
       // Culling parameters.
       var dt = this.viewport.currentDisplayTransform;
@@ -90,7 +90,7 @@
 
       // Draw the memory dumps.
       var items = this.items_;
-      var loI = tv.b.findLowIndexInSortedArray(
+      var loI = tr.b.findLowIndexInSortedArray(
           items,
           function(item) { return item.start; },
           viewLWorld);
@@ -160,7 +160,7 @@
         return;
 
       var itemRadiusWorld = viewPixWidthWorld * this.dumpRadiusView;
-      tv.b.iterateOverIntersectingIntervals(
+      tr.b.iterateOverIntersectingIntervals(
           this.items_,
           function(x) { return x.start - itemRadiusWorld; },
           function(x) { return 2 * itemRadiusWorld; },
@@ -185,7 +185,7 @@
         return;
 
       var items = this.items_;
-      var index = tv.b.findFirstIndexInArray(items, function(item) {
+      var index = tr.b.findFirstIndexInArray(items, function(item) {
         return item.modelItem === event;
       });
       if (index === -1)
@@ -207,7 +207,7 @@
       if (this.items_ === undefined)
         return;
 
-      var item = tv.b.findClosestElementInSortedArray(
+      var item = tr.b.findClosestElementInSortedArray(
           this.items_,
           function(x) { return x.start; },
           worldX,
@@ -227,14 +227,14 @@
    * @extends {ProxySelectableItem}
    */
   function LetterDot(modelItem, dotLetter, colorId, start) {
-    tv.c.trace_model.ProxySelectableItem.call(this, modelItem);
+    tr.model.ProxySelectableItem.call(this, modelItem);
     this.dotLetter = dotLetter;
     this.colorId = colorId;
     this.start = start;
   };
 
   LetterDot.prototype = {
-    __proto__: tv.c.trace_model.ProxySelectableItem.prototype
+    __proto__: tr.model.ProxySelectableItem.prototype
   };
 
   return {
diff --git a/trace-viewer/trace_viewer/core/tracks/letter_dot_track_test.html b/trace-viewer/trace_viewer/core/tracks/letter_dot_track_test.html
index 3ecc8ba..aa028e5 100644
--- a/trace-viewer/trace_viewer/core/tracks/letter_dot_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/letter_dot_track_test.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/selection_state.html">
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/tracks/drawing_container.html">
 <link rel="import" href="/core/tracks/letter_dot_track.html">
@@ -14,12 +14,12 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var LetterDotTrack = tv.c.tracks.LetterDotTrack;
-  var LetterDot = tv.c.tracks.LetterDot;
-  var Selection = tv.c.Selection;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Viewport = tv.c.TimelineViewport;
+tr.b.unittest.testSuite(function() {
+  var LetterDotTrack = tr.c.tracks.LetterDotTrack;
+  var LetterDot = tr.c.tracks.LetterDot;
+  var Selection = tr.c.Selection;
+  var SelectionState = tr.model.SelectionState;
+  var Viewport = tr.c.TimelineViewport;
 
   var createItems = function() {
     var items = [
@@ -37,7 +37,7 @@
     var div = document.createElement('div');
 
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = LetterDotTrack(viewport);
@@ -47,7 +47,7 @@
     drawingContainer.invalidate();
 
     track.items = items;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 60, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
diff --git a/trace-viewer/trace_viewer/core/tracks/memory_dump_track_test_utils.html b/trace-viewer/trace_viewer/core/tracks/memory_dump_track_test_utils.html
index 96617a6..ea07ee4 100644
--- a/trace-viewer/trace_viewer/core/tracks/memory_dump_track_test_utils.html
+++ b/trace-viewer/trace_viewer/core/tracks/memory_dump_track_test_utils.html
@@ -5,12 +5,12 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/attribute.html">
-<link rel="import" href="/core/trace_model/global_memory_dump.html">
-<link rel="import" href="/core/trace_model/memory_allocator_dump.html">
-<link rel="import" href="/core/trace_model/process_memory_dump.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/global_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
+<link rel="import" href="/model/process_memory_dump.html">
+<link rel="import" href="/model/selection_state.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
@@ -18,15 +18,14 @@
 /**
  * @fileoverview Helper functions for memory dump track tests.
  */
-tv.exportTo('tv.c.tracks', function() {
-  var ProcessMemoryDump = tv.c.trace_model.ProcessMemoryDump;
-  var GlobalMemoryDump = tv.c.trace_model.GlobalMemoryDump;
-  var MemoryAllocatorDump = tv.c.trace_model.MemoryAllocatorDump;
-  var VMRegion = tv.c.trace_model.VMRegion;
-  var VMRegionByteStats = tv.c.trace_model.VMRegionByteStats;
-  var TraceModel = tv.c.TraceModel;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.exportTo('tr.c.tracks', function() {
+  var ProcessMemoryDump = tr.model.ProcessMemoryDump;
+  var GlobalMemoryDump = tr.model.GlobalMemoryDump;
+  var MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+  var VMRegion = tr.model.VMRegion;
+  var VMRegionByteStats = tr.model.VMRegionByteStats;
+  var ScalarAttribute = tr.model.ScalarAttribute;
+  var SelectionState = tr.model.SelectionState;
 
   function createVMRegions(pssValues) {
     return pssValues.map(function(pssValue, i) {
@@ -35,20 +34,20 @@
         sizeInBytes: 1000,
         protectionFlags: VMRegion.PROTECTION_FLAG_READ,
         mappedFile: '[stack' + i + ']',
-        byteStats: VMRegionByteStats.fromDict({
-          privateResident: pssValue / 3,
-          sharedResident: pssValue * 3,
+        byteStats: {
+          privateDirtyResident: pssValue / 3,
+          swapped: pssValue * 3,
           proportionalResident: pssValue
-        })
+        }
       });
     });
   }
 
   function createAllocatorDumps(memoryDump, dumpSizes) {
     var allocatorDumps = [];
-    tv.b.iterItems(dumpSizes, function(allocatorName, size) {
+    tr.b.iterItems(dumpSizes, function(allocatorName, size) {
       var dump = new MemoryAllocatorDump(memoryDump, allocatorName);
-      dump.addAttribute('outer_size', new ScalarAttribute('bytes', size));
+      dump.addAttribute('size', new ScalarAttribute('bytes', size));
       allocatorDumps.push(dump);
     });
     return allocatorDumps;
@@ -72,7 +71,7 @@
     var maybeDumpSizes = function(dumpSizes) {
       return withAllocatorDumps ? dumpSizes : undefined;
     };
-    return tv.c.test_utils.newModel(function(model) {
+    return tr.c.test_utils.newModel(function(model) {
       // Construct a model with three processes.
       var pa = model.getOrCreateProcess(3);
       var pb = model.getOrCreateProcess(6);
@@ -90,7 +89,7 @@
       addProcessMemoryDump(gmd2, pb, 4.99, maybePssValues([100, 50]),
           maybeDumpSizes({v8: 512}));
       addProcessMemoryDump(gmd2, pc, 5.12, undefined,
-          maybeDumpSizes({oilpan: 128, v8: 256}));
+          maybeDumpSizes({oilpan: 128, v8: 256, tracing: 65536}));
 
       var gmd3 = new GlobalMemoryDump(model, 15);
       model.globalMemoryDumps.push(gmd3);
diff --git a/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util.html b/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util.html
index 4f8fcd3..07b53dc 100644
--- a/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util.html
+++ b/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util.html
@@ -15,9 +15,12 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
-  var ALLOCATOR_SIZE_ATTRIBUTE_NAME = 'outer_size';
+  // TODO(petrcermak): Remove support for the old default attribute name once
+  // the correspoding change lands in Chromium.
+  var ALLOCATOR_SIZE_ATTRIBUTE_OLD_NAME = 'outer_size';
+  var ALLOCATOR_SIZE_ATTRIBUTE_NAME = 'size';
 
   /**
    * Add numeric values from a source dictionary to the numeric values in
@@ -28,7 +31,7 @@
    * destination dictionary (first argument) to {a: 1, b: 5, c: 4}.
    */
   function addDictionary(dstDict, srcDict) {
-    tv.b.iterItems(srcDict, function(key, value) {
+    tr.b.iterItems(srcDict, function(key, value) {
       var existingValue = dstDict[key];
       if (existingValue === undefined)
         existingValue = 0;
@@ -46,8 +49,16 @@
       return {};
     var allocatorSizes = {};
     allocatorDumps.forEach(function(allocatorDump) {
+      // Don't show tracing overhead in the charts.
+      // TODO(petrcermak): Find a less hacky way to do this.
+      if (allocatorDump.fullName === 'tracing')
+        return;
       var allocatorSize = allocatorDump.attributes[
           ALLOCATOR_SIZE_ATTRIBUTE_NAME];
+      if (allocatorSize === undefined) {
+        allocatorSize = allocatorDump.attributes[
+            ALLOCATOR_SIZE_ATTRIBUTE_OLD_NAME];
+      }
       if (allocatorSize === undefined)
         return;
       var allocatorSizeValue = allocatorSize.value;
@@ -65,7 +76,7 @@
    */
   function getGlobalMemoryDumpAllocatorSizes(globalMemoryDump) {
     var globalAllocatorSizes = {};
-    tv.b.iterItems(globalMemoryDump.processMemoryDumps,
+    tr.b.iterItems(globalMemoryDump.processMemoryDumps,
         function(pid, processMemoryDump) {
       addDictionary(globalAllocatorSizes,
           getProcessMemoryDumpAllocatorSizes(processMemoryDump));
@@ -83,7 +94,7 @@
     var allocatorNameToPoints = {};
     var dumpsData = memoryDumps.map(function(memoryDump) {
       var allocatorSizes = memoryDumpToAllocatorSizesFn(memoryDump);
-      tv.b.iterItems(allocatorSizes, function(allocatorName) {
+      tr.b.iterItems(allocatorSizes, function(allocatorName) {
         allocatorNameToPoints[allocatorName] = [];
       });
       return {dump: memoryDump, sizes: allocatorSizes};
@@ -97,25 +108,25 @@
     dumpsData.forEach(function(dumpData) {
       var memoryDump = dumpData.dump;
       var allocatorSizes = dumpData.sizes;
-      tv.b.iterItems(allocatorNameToPoints, function(allocatorName, points) {
+      tr.b.iterItems(allocatorNameToPoints, function(allocatorName, points) {
         var allocatorSize = allocatorSizes[allocatorName] || 0;
-        points.push(new tv.c.tracks.ChartPoint(
+        points.push(new tr.c.tracks.ChartPoint(
             memoryDump, memoryDump.start, allocatorSize));
       });
     });
 
     // Create one common axis for all allocated memory chart series.
-    var axis = new tv.c.tracks.ChartAxis(0);
+    var axis = new tr.c.tracks.ChartAxis(0);
 
     // Build a chart series for each allocator.
     var series = [];
-    tv.b.iterItems(allocatorNameToPoints, function(allocatorName, points) {
-      var colorId = tv.b.ui.getColorIdForGeneralPurposeString(allocatorName);
+    tr.b.iterItems(allocatorNameToPoints, function(allocatorName, points) {
+      var colorId = tr.b.ui.getColorIdForGeneralPurposeString(allocatorName);
       var renderingConfig = {
-        chartType: tv.c.tracks.ChartSeriesType.LINE,
+        chartType: tr.c.tracks.ChartSeriesType.LINE,
         colorId: colorId
       };
-      series.push(new tv.c.tracks.ChartSeries(points, axis, renderingConfig));
+      series.push(new tr.c.tracks.ChartSeries(points, axis, renderingConfig));
     });
 
     return series;
@@ -126,9 +137,9 @@
    * inside).
    */
   function buildMemoryLetterDots(memoryDumps) {
-    var memoryColorId = tv.b.ui.getColorIdForReservedName('memory_dump');
+    var memoryColorId = tr.b.ui.getColorIdForReservedName('memory_dump');
     return memoryDumps.map(function(memoryDump) {
-      return new tv.c.tracks.LetterDot(
+      return new tr.c.tracks.LetterDot(
           memoryDump, 'M', memoryColorId, memoryDump.start);
     });
   }
@@ -152,14 +163,14 @@
     // Find all processes that dump memory at least once.
     var pidToProcess = {};
     globalMemoryDumps.forEach(function(globalDump) {
-      tv.b.iterItems(globalDump.processMemoryDumps, function(pid, processDump) {
+      tr.b.iterItems(globalDump.processMemoryDumps, function(pid, processDump) {
         pidToProcess[pid] = processDump.process;
       });
     });
 
     // Build one list of points for each instrumented process.
     var pidToPoints = {};
-    tv.b.iterItems(pidToProcess, function(pid, process) {
+    tr.b.iterItems(pidToProcess, function(pid, process) {
       pidToPoints[pid] = [];
     });
 
@@ -167,15 +178,15 @@
     // each process and append it to the corresponding list of points.
     globalMemoryDumps.forEach(function(globalDump) {
       var pssBase = 0;
-      tv.b.iterItems(pidToPoints, function(pid, points) {
+      tr.b.iterItems(pidToPoints, function(pid, points) {
         var processMemoryDump = globalDump.processMemoryDumps[pid];
         var pss;
         if (processMemoryDump === undefined) {
           // If no dump was found, assume that the process is dead.
           pss = 0;
         } else {
-          pss =
-              processMemoryDump.mostRecentTotalProportionalResidentSizeInBytes;
+          pss = processMemoryDump.getMostRecentTotalVmRegionStat(
+              'proportionalResident');
           if (pss === undefined) {
             // If the dump does not provide the necessary information (namely
             // most recent VM regions), assume zero.
@@ -183,27 +194,27 @@
           }
         }
         var cumulativePss = pssBase + pss;
-        points.push(new tv.c.tracks.ChartPoint(
+        points.push(new tr.c.tracks.ChartPoint(
             globalDump, globalDump.start, cumulativePss, pssBase));
         pssBase = cumulativePss;
       });
     });
 
     // Create one common axis for all used memory chart series.
-    var axis = new tv.c.tracks.ChartAxis(0);
+    var axis = new tr.c.tracks.ChartAxis(0);
 
     // Build a chart series for each instrumented process.
     var series = [];
-    tv.b.iterItems(pidToPoints, function(pid, points) {
+    tr.b.iterItems(pidToPoints, function(pid, points) {
       var process = pidToProcess[pid];
-      var colorId = tv.b.ui.getColorIdForGeneralPurposeString(
+      var colorId = tr.b.ui.getColorIdForGeneralPurposeString(
           process.userFriendlyName);
       var renderingConfig = {
-        chartType: tv.c.tracks.ChartSeriesType.AREA,
+        chartType: tr.c.tracks.ChartSeriesType.AREA,
         colorId: colorId,
         backgroundOpacity: 0.8
       };
-      series.push(new tv.c.tracks.ChartSeries(points, axis, renderingConfig));
+      series.push(new tr.c.tracks.ChartSeries(points, axis, renderingConfig));
     });
 
     // Show the first series (with the smallest cumulative value) at the top.
diff --git a/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util_test.html b/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util_test.html
index 9b72abd..dafdd81 100644
--- a/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/memory_dump_track_util_test.html
@@ -6,21 +6,21 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/selection_state.html">
 <link rel="import" href="/core/tracks/memory_dump_track_test_utils.html">
 <link rel="import" href="/core/tracks/memory_dump_track_util.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var createTestGlobalMemoryDumps = tv.c.tracks.createTestGlobalMemoryDumps;
-  var createTestProcessMemoryDumps = tv.c.tracks.createTestProcessMemoryDumps;
+tr.b.unittest.testSuite(function() {
+  var SelectionState = tr.model.SelectionState;
+  var createTestGlobalMemoryDumps = tr.c.tracks.createTestGlobalMemoryDumps;
+  var createTestProcessMemoryDumps = tr.c.tracks.createTestProcessMemoryDumps;
 
   test('buildMemoryLetterDots_withoutVMRegions', function() {
     var dumps = createTestGlobalMemoryDumps(false, false);
-    var items = tv.c.tracks.buildMemoryLetterDots(dumps);
+    var items = tr.c.tracks.buildMemoryLetterDots(dumps);
 
     assert.lengthOf(items, 4);
     assert.equal(items[0].start, 0);
@@ -36,7 +36,7 @@
 
   test('buildMemoryLetterDots_withVMRegions', function() {
     var dumps = createTestGlobalMemoryDumps(false, false);
-    var items = tv.c.tracks.buildMemoryLetterDots(dumps);
+    var items = tr.c.tracks.buildMemoryLetterDots(dumps);
 
     assert.lengthOf(items, 4);
     assert.equal(items[0].start, 0);
@@ -52,14 +52,14 @@
 
   test('buildGlobalUsedMemoryChartSeries_withoutVMRegions', function() {
     var dumps = createTestGlobalMemoryDumps(false, false);
-    var series = tv.c.tracks.buildGlobalUsedMemoryChartSeries(dumps);
+    var series = tr.c.tracks.buildGlobalUsedMemoryChartSeries(dumps);
 
     assert.isUndefined(series);
   });
 
   test('buildGlobalUsedMemoryChartSeries_withVMRegions', function() {
     var dumps = createTestGlobalMemoryDumps(true, false);
-    var series = tv.c.tracks.buildGlobalUsedMemoryChartSeries(dumps);
+    var series = tr.c.tracks.buildGlobalUsedMemoryChartSeries(dumps);
 
     assert.lengthOf(series, 3);
 
@@ -130,7 +130,7 @@
   test('buildGlobalAllocatedMemoryChartSeries_withoutMemoryAllocatorDumps',
       function() {
     var dumps = createTestGlobalMemoryDumps(false, false);
-    var series = tv.c.tracks.buildGlobalAllocatedMemoryChartSeries(dumps);
+    var series = tr.c.tracks.buildGlobalAllocatedMemoryChartSeries(dumps);
 
     assert.isUndefined(series);
   });
@@ -138,7 +138,7 @@
   test('buildGlobalAllocatedMemoryChartSeries_withMemoryAllocatorDumps',
       function() {
     var dumps = createTestGlobalMemoryDumps(false, true);
-    var series = tv.c.tracks.buildGlobalAllocatedMemoryChartSeries(dumps);
+    var series = tr.c.tracks.buildGlobalAllocatedMemoryChartSeries(dumps);
 
     assert.lengthOf(series, 2);
 
@@ -185,7 +185,7 @@
   test('buildProcessAllocatedMemoryChartSeries_withoutMemoryAllocatorDumps',
       function() {
     var dumps = createTestProcessMemoryDumps(false, false);
-    var series = tv.c.tracks.buildProcessAllocatedMemoryChartSeries(dumps);
+    var series = tr.c.tracks.buildProcessAllocatedMemoryChartSeries(dumps);
 
     assert.isUndefined(series);
   });
@@ -193,8 +193,10 @@
   test('buildProcessAllocatedMemoryChartSeries_withMemoryAllocatorDumps',
       function() {
     var dumps = createTestProcessMemoryDumps(false, true);
-    var series = tv.c.tracks.buildProcessAllocatedMemoryChartSeries(dumps);
+    var series = tr.c.tracks.buildProcessAllocatedMemoryChartSeries(dumps);
 
+    // There should be only 2 series (because 'tracing' is not shown in the
+    // charts).
     assert.lengthOf(series, 2);
 
     var so = series[0];
diff --git a/trace-viewer/trace_viewer/core/tracks/trace_model_track.html b/trace-viewer/trace_viewer/core/tracks/model_track.html
similarity index 85%
rename from trace-viewer/trace_viewer/core/tracks/trace_model_track.html
rename to trace-viewer/trace_viewer/core/tracks/model_track.html
index 6646f09..b1b0dc9 100644
--- a/trace-viewer/trace_viewer/core/tracks/trace_model_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/model_track.html
@@ -23,11 +23,11 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   // TODO(nduca): Move this elsewhere and make it non-hacky.
   function HackyMultiRowTrack(viewport, model) {
-    var mrt = new tv.c.tracks.MultiRowTrack(viewport);
+    var mrt = new tr.c.tracks.MultiRowTrack(viewport);
     mrt.heading = 'Interactions';
     mrt.buildSubRows_ = function(slices) {
       slices.sort(function(x, y) {
@@ -36,18 +36,18 @@
           return r;
         return x.start - y.start;
       });
-      return tv.c.tracks.AsyncSliceGroupTrack.prototype.buildSubRows_.call(
+      return tr.c.tracks.AsyncSliceGroupTrack.prototype.buildSubRows_.call(
           {}, slices, true);
     };
     mrt.addSubTrack_ = function(slices) {
-      var track = new tv.c.tracks.SliceTrack(this.viewport);
+      var track = new tr.c.tracks.SliceTrack(this.viewport);
       track.slices = slices;
       this.appendChild(track);
       return track;
     };
 
     mrt.setItemsToGroup(model.interaction_records, {
-      guid: tv.b.GUID.allocate(),
+      guid: tr.b.GUID.allocate(),
       model: model,
       getSettingsKey: function() {
         return undefined;
@@ -57,27 +57,25 @@
     return mrt;
   }
 
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var EventPresenter = tv.c.EventPresenter;
+  var SelectionState = tr.model.SelectionState;
+  var EventPresenter = tr.c.EventPresenter;
 
   /**
-   * Visualizes a Model by building ProcessTracks and
-   * CpuTracks.
+   * Visualizes a Model by building ProcessTracks and CpuTracks.
    * @constructor
    */
-  var TraceModelTrack = tv.b.ui.define(
-      'trace-model-track', tv.c.tracks.ContainerTrack);
+  var ModelTrack = tr.b.ui.define('model-track', tr.c.tracks.ContainerTrack);
 
 
-  TraceModelTrack.prototype = {
+  ModelTrack.prototype = {
 
-    __proto__: tv.c.tracks.ContainerTrack.prototype,
+    __proto__: tr.c.tracks.ContainerTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
       this.classList.add('model-track');
 
-      var typeInfos = tv.c.tracks.Highlighter.getAllRegisteredTypeInfos();
+      var typeInfos = tr.c.tracks.Highlighter.getAllRegisteredTypeInfos();
       this.highlighters_ = typeInfos.map(
         function(typeInfo) {
           return new typeInfo.constructor(viewport);
@@ -98,7 +96,7 @@
     },
 
     detach: function() {
-      tv.c.tracks.ContainerTrack.prototype.detach.call(this);
+      tr.c.tracks.ContainerTrack.prototype.detach.call(this);
     },
 
     get model() {
@@ -138,13 +136,13 @@
       }
 
       if (this.model_.alerts.length) {
-        var at = new tv.c.tracks.AlertTrack(this.viewport_);
+        var at = new tr.c.tracks.AlertTrack(this.viewport_);
         at.alerts = this.model_.alerts;
         this.appendChild(at);
       }
 
       if (this.model_.globalMemoryDumps.length) {
-        var gmdt = new tv.c.tracks.GlobalMemoryDumpTrack(this.viewport_);
+        var gmdt = new tr.c.tracks.GlobalMemoryDumpTrack(this.viewport_);
         gmdt.memoryDumps = this.model_.globalMemoryDumps;
         this.appendChild(gmdt);
       }
@@ -153,12 +151,12 @@
 
       // Get a sorted list of processes.
       var processes = this.model_.getAllProcesses();
-      processes.sort(tv.c.trace_model.Process.compare);
+      processes.sort(tr.model.Process.compare);
 
       for (var i = 0; i < processes.length; ++i) {
         var process = processes[i];
 
-        var track = new tv.c.tracks.ProcessTrack(this.viewport);
+        var track = new tr.c.tracks.ProcessTrack(this.viewport);
         track.process = process;
         if (!track.hasVisibleContent)
           continue;
@@ -210,7 +208,7 @@
 
     appendKernelTrack_: function() {
       var kernel = this.model.kernel;
-      var track = new tv.c.tracks.KernelTrack(this.viewport);
+      var track = new tr.c.tracks.KernelTrack(this.viewport);
       track.kernel = this.model.kernel;
       if (!track.hasVisibleContent)
         return;
@@ -234,13 +232,13 @@
       var viewRWorld = dt.xViewToWorld(bounds.width * pixelRatio);
 
       switch (type) {
-        case tv.c.tracks.DrawType.GRID:
+        case tr.c.tracks.DrawType.GRID:
           this.viewport.drawMajorMarkLines(ctx);
           // The model is the only thing that draws grid lines.
           ctx.restore();
           return;
 
-        case tv.c.tracks.DrawType.FLOW_ARROWS:
+        case tr.c.tracks.DrawType.FLOW_ARROWS:
           if (this.model_.flowIntervalTree.size === 0) {
             ctx.restore();
             return;
@@ -250,12 +248,12 @@
           ctx.restore();
           return;
 
-        case tv.c.tracks.DrawType.INSTANT_EVENT:
+        case tr.c.tracks.DrawType.INSTANT_EVENT:
           if (!this.model_.instantEvents ||
               this.model_.instantEvents.length === 0)
             break;
 
-          tv.c.drawInstantSlicesAsLines(
+          tr.c.drawInstantSlicesAsLines(
               ctx,
               this.viewport.currentDisplayTransform,
               viewLWorld,
@@ -266,7 +264,7 @@
 
           break;
 
-        case tv.c.tracks.DrawType.MARKERS:
+        case tr.c.tracks.DrawType.MARKERS:
           if (!this.viewport.interestRange.isEmpty) {
             this.viewport.interestRange.draw(ctx, viewLWorld, viewRWorld);
             this.viewport.interestRange.drawIndicators(
@@ -275,7 +273,7 @@
           ctx.restore();
           return;
 
-        case tv.c.tracks.DrawType.HIGHLIGHTS:
+        case tr.c.tracks.DrawType.HIGHLIGHTS:
           for (var i = 0; i < this.highlighters_.length; i++) {
             this.highlighters_[i].drawHighlight(ctx, dt, viewLWorld, viewRWorld,
                 bounds.height);
@@ -283,7 +281,7 @@
           ctx.restore();
           return;
 
-        case tv.c.tracks.DrawType.ANNOTATIONS:
+        case tr.c.tracks.DrawType.ANNOTATIONS:
           for (var i = 0; i < this.annotationViews_.length; i++) {
             this.annotationViews_[i].draw(ctx);
           }
@@ -292,7 +290,7 @@
       }
       ctx.restore();
 
-      tv.c.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
+      tr.c.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
     },
 
     drawFlowArrows_: function(viewLWorld, viewRWorld) {
@@ -309,9 +307,16 @@
       var events =
           this.model_.flowIntervalTree.findIntersection(viewLWorld, viewRWorld);
 
+      // When not showing flow events, show only highlighted/selected ones.
+      var onlyHighlighted = !this.viewport.showFlowEvents;
       var canvasBounds = ctx.canvas.getBoundingClientRect();
-      for (var i = 0; i < events.length; ++i)
+      for (var i = 0; i < events.length; ++i) {
+        if (onlyHighlighted &&
+            events[i].selectionState !== SelectionState.SELECTED &&
+            events[i].selectionState !== SelectionState.HIGHLIGHTED)
+          continue;
         this.drawFlowArrow_(ctx, events[i], canvasBounds, pixWidth);
+      }
     },
 
     drawFlowArrow_: function(ctx, flowEvent,
@@ -394,7 +399,7 @@
       var tipX = flowEvent.end;
       var tipY = pixelEndY;
       var arrowHeight = (endBounds.height / 4) * pixelRatio;
-      tv.c.drawTriangle(ctx,
+      tr.c.drawTriangle(ctx,
           tipX, tipY,
           tipX - arrowWidth, tipY - arrowHeight,
           tipX - arrowWidth, tipY + arrowHeight);
@@ -415,13 +420,13 @@
       function onPickHit(instantEvent) {
         selection.push(instantEvent);
       }
-      tv.b.iterateOverIntersectingIntervals(this.model_.instantEvents,
+      tr.b.iterateOverIntersectingIntervals(this.model_.instantEvents,
           function(x) { return x.start; },
           function(x) { return x.duration; },
           loWX, hiWX,
           onPickHit.bind(this));
 
-      tv.c.tracks.ContainerTrack.prototype.
+      tr.c.tracks.ContainerTrack.prototype.
           addIntersectingEventsInRangeToSelectionInWorldSpace.
           apply(this, arguments);
     },
@@ -430,13 +435,13 @@
                                          selection) {
       this.addClosestInstantEventToSelection(this.model_.instantEvents,
                                              worldX, worldMaxDist, selection);
-      tv.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.
+      tr.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.
           apply(this, arguments);
     }
   };
 
   return {
-    TraceModelTrack: TraceModelTrack
+    ModelTrack: ModelTrack
   };
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/tracks/multi_row_track.html b/trace-viewer/trace_viewer/core/tracks/multi_row_track.html
index 69c323b..a897b6b 100644
--- a/trace-viewer/trace_viewer/core/tracks/multi_row_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/multi_row_track.html
@@ -6,30 +6,28 @@
 -->
 
 <link rel="import" href="/core/tracks/container_track.html">
-<link rel="import" href="/core/trace_model/trace_model_settings.html">
 <link rel="import" href="/base/sorted_array_utils.html">
 <link rel="import" href="/base/ui.html">
+<link rel="import" href="/model/model_settings.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
-  var TraceModelSettings = tv.c.TraceModelSettings;
-
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays a group of objects in multiple rows.
    * @constructor
    * @extends {ContainerTrack}
    */
-  var MultiRowTrack = tv.b.ui.define(
-      'multi-row-track', tv.c.tracks.ContainerTrack);
+  var MultiRowTrack = tr.b.ui.define(
+      'multi-row-track', tr.c.tracks.ContainerTrack);
 
   MultiRowTrack.prototype = {
 
-    __proto__: tv.c.tracks.ContainerTrack.prototype,
+    __proto__: tr.c.tracks.ContainerTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
       this.tooltip_ = '';
       this.heading_ = '';
 
@@ -99,7 +97,7 @@
       this.expanded = !this.expanded;
 
       if (this.groupingSource_) {
-        var modelSettings = new TraceModelSettings(
+        var modelSettings = new tr.model.ModelSettings(
             this.groupingSource_.model);
         modelSettings.setSettingFor(this.groupingSource_, 'expanded',
                                     this.expanded);
@@ -111,7 +109,7 @@
     updateExpandedStateFromGroupingSource_: function() {
       if (this.groupingSource_) {
         var numSubRows = this.subRows.length;
-        var modelSettings = new TraceModelSettings(
+        var modelSettings = new tr.model.ModelSettings(
             this.groupingSource_.model);
         if (numSubRows > 1) {
           var defaultExpanded;
@@ -139,7 +137,7 @@
     },
 
     updateContents_: function() {
-      tv.c.tracks.ContainerTrack.prototype.updateContents_.call(this);
+      tr.c.tracks.ContainerTrack.prototype.updateContents_.call(this);
       if (!this.itemsToGroup_) {
         this.updateHeadingAndTooltip_();
         this.currentSubRows_ = [];
diff --git a/trace-viewer/trace_viewer/core/tracks/object_instance_group_track.html b/trace-viewer/trace_viewer/core/tracks/object_instance_group_track.html
index c454d25..2e87ae4 100644
--- a/trace-viewer/trace_viewer/core/tracks/object_instance_group_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/object_instance_group_track.html
@@ -14,21 +14,21 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays a ObjectInstanceGroup.
    * @constructor
    * @extends {ContainerTrack}
    */
-  var ObjectInstanceGroupTrack = tv.b.ui.define(
-      'object-instance-group-track', tv.c.tracks.MultiRowTrack);
+  var ObjectInstanceGroupTrack = tr.b.ui.define(
+      'object-instance-group-track', tr.c.tracks.MultiRowTrack);
 
   ObjectInstanceGroupTrack.prototype = {
 
-    __proto__: tv.c.tracks.MultiRowTrack.prototype,
+    __proto__: tr.c.tracks.MultiRowTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
       this.classList.add('object-instance-group-track');
       this.objectInstances_ = undefined;
     },
@@ -43,7 +43,7 @@
 
     addSubTrack_: function(objectInstances) {
       var hasMultipleRows = this.subRows.length > 1;
-      var track = new tv.c.tracks.ObjectInstanceTrack(this.viewport);
+      var track = new tr.c.tracks.ObjectInstanceTrack(this.viewport);
       track.objectInstances = objectInstances;
       this.appendChild(track);
       return track;
diff --git a/trace-viewer/trace_viewer/core/tracks/object_instance_track.html b/trace-viewer/trace_viewer/core/tracks/object_instance_track.html
index 4dc1bae..c636a00 100644
--- a/trace-viewer/trace_viewer/core/tracks/object_instance_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/object_instance_track.html
@@ -8,7 +8,7 @@
 <link rel="stylesheet" href="/core/tracks/object_instance_track.css">
 
 <link rel="import" href="/base/extension_registry.html">
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/model/event.html">
 <link rel="import" href="/core/tracks/heading_track.html">
 <link rel="import" href="/core/event_presenter.html">
 <link rel="import" href="/base/sorted_array_utils.html">
@@ -17,10 +17,10 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var EventPresenter = tv.c.EventPresenter;
+  var SelectionState = tr.model.SelectionState;
+  var EventPresenter = tr.c.EventPresenter;
 
   /**
    * A track that displays an array of Slice objects.
@@ -28,14 +28,14 @@
    * @extends {HeadingTrack}
    */
 
-  var ObjectInstanceTrack = tv.b.ui.define(
-      'object-instance-track', tv.c.tracks.HeadingTrack);
+  var ObjectInstanceTrack = tr.b.ui.define(
+      'object-instance-track', tr.c.tracks.HeadingTrack);
 
   ObjectInstanceTrack.prototype = {
-    __proto__: tv.c.tracks.HeadingTrack.prototype,
+    __proto__: tr.c.tracks.HeadingTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
       this.classList.add('object-instance-track');
       this.objectInstances_ = [];
       this.objectSnapshots_ = [];
@@ -78,7 +78,7 @@
 
     draw: function(type, viewLWorld, viewRWorld) {
       switch (type) {
-        case tv.c.tracks.DrawType.GENERAL_EVENT:
+        case tr.c.tracks.DrawType.GENERAL_EVENT:
           this.drawLetterDots_(viewLWorld, viewRWorld);
           break;
       }
@@ -105,7 +105,7 @@
 
       // Instances
       var objectInstances = this.objectInstances_;
-      var loI = tv.b.findLowIndexInSortedArray(
+      var loI = tr.b.findLowIndexInSortedArray(
           objectInstances,
           function(instance) {
             return instance.deletionTs;
@@ -127,7 +127,7 @@
 
       // Snapshots. Has to run in worldspace because ctx.arc gets transformed.
       var objectSnapshots = this.objectSnapshots_;
-      loI = tv.b.findLowIndexInSortedArray(
+      loI = tr.b.findLowIndexInSortedArray(
           objectSnapshots,
           function(snapshot) {
             return snapshot.ts + snapshotRadiusWorld;
@@ -204,7 +204,7 @@
       }
       var snapshotRadiusView = this.snapshotRadiusView;
       var snapshotRadiusWorld = viewPixWidthWorld * snapshotRadiusView;
-      tv.b.iterateOverIntersectingIntervals(
+      tr.b.iterateOverIntersectingIntervals(
           this.objectSnapshots_,
           function(x) { return x.ts - snapshotRadiusWorld; },
           function(x) { return 2 * snapshotRadiusWorld; },
@@ -214,7 +214,7 @@
         return;
 
       // Try picking instances.
-      tv.b.iterateOverIntersectingIntervals(
+      tr.b.iterateOverIntersectingIntervals(
           this.objectInstances_,
           function(x) { return x.creationTs; },
           function(x) { return x.deletionTs - x.creationTs; },
@@ -234,9 +234,9 @@
      */
     addEventNearToProvidedEventToSelection: function(event, offset, selection) {
       var events;
-      if (event instanceof tv.c.trace_model.ObjectSnapshot)
+      if (event instanceof tr.model.ObjectSnapshot)
         events = this.objectSnapshots_;
-      else if (event instanceof tv.c.trace_model.ObjectInstance)
+      else if (event instanceof tr.model.ObjectInstance)
         events = this.objectInstances_;
       else
         throw new Error('Unrecognized event');
@@ -255,7 +255,7 @@
 
     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
                                          selection) {
-      var snapshot = tv.b.findClosestElementInSortedArray(
+      var snapshot = tr.b.findClosestElementInSortedArray(
           this.objectSnapshots_,
           function(x) { return x.ts; },
           worldX,
@@ -273,9 +273,9 @@
   };
 
 
-  var options = new tv.b.ExtensionRegistryOptions(
-      tv.b.TYPE_BASED_REGISTRY_MODE);
-  tv.b.decorateExtensionRegistry(ObjectInstanceTrack, options);
+  var options = new tr.b.ExtensionRegistryOptions(
+      tr.b.TYPE_BASED_REGISTRY_MODE);
+  tr.b.decorateExtensionRegistry(ObjectInstanceTrack, options);
 
   return {
     ObjectInstanceTrack: ObjectInstanceTrack
diff --git a/trace-viewer/trace_viewer/core/tracks/object_instance_track_test.html b/trace-viewer/trace_viewer/core/tracks/object_instance_track_test.html
index e28d11f..2e46748 100644
--- a/trace-viewer/trace_viewer/core/tracks/object_instance_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/object_instance_track_test.html
@@ -7,8 +7,8 @@
 
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/object_collection.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/object_collection.html">
+<link rel="import" href="/model/selection_state.html">
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/tracks/drawing_container.html">
 <link rel="import" href="/core/tracks/object_instance_track.html">
@@ -16,18 +16,18 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
-  var Selection = tv.c.Selection;
-  var ObjectInstanceTrack = tv.c.tracks.ObjectInstanceTrack;
-  var Viewport = tv.c.TimelineViewport;
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
+  var Selection = tr.c.Selection;
+  var ObjectInstanceTrack = tr.c.tracks.ObjectInstanceTrack;
+  var Viewport = tr.c.TimelineViewport;
 
   var createObjects = function() {
-    var objects = new tv.c.trace_model.ObjectCollection({});
-    objects.idWasCreated('0x1000', 'tv.e.cc', 'Frame', 10);
-    objects.addSnapshot('0x1000', 'tv.e.cc', 'Frame', 10, 'snapshot-1');
-    objects.addSnapshot('0x1000', 'tv.e.cc', 'Frame', 25, 'snapshot-2');
-    objects.addSnapshot('0x1000', 'tv.e.cc', 'Frame', 40, 'snapshot-3');
-    objects.idWasDeleted('0x1000', 'tv.e.cc', 'Frame', 45);
+    var objects = new tr.model.ObjectCollection({});
+    objects.idWasCreated('0x1000', 'tr.e.cc', 'Frame', 10);
+    objects.addSnapshot('0x1000', 'tr.e.cc', 'Frame', 10, 'snapshot-1');
+    objects.addSnapshot('0x1000', 'tr.e.cc', 'Frame', 25, 'snapshot-2');
+    objects.addSnapshot('0x1000', 'tr.e.cc', 'Frame', 40, 'snapshot-3');
+    objects.idWasDeleted('0x1000', 'tr.e.cc', 'Frame', 45);
 
     objects.idWasCreated('0x1001', 'skia', 'Picture', 20);
     objects.addSnapshot('0x1001', 'skia', 'Picture', 20, 'snapshot-1');
@@ -39,12 +39,12 @@
     var objects = createObjects();
     var frames = objects.getAllInstancesByTypeName()['Frame'];
     frames[0].snapshots[1].selectionState =
-        tv.c.trace_model.SelectionState.SELECTED;
+        tr.model.SelectionState.SELECTED;
 
     var div = document.createElement('div');
 
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = ObjectInstanceTrack(viewport);
@@ -55,7 +55,7 @@
 
     track.heading = 'testBasic';
     track.objectInstances = frames;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 50, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
@@ -78,14 +78,14 @@
     track.addIntersectingEventsInRangeToSelectionInWorldSpace(
         9.98, 9.99, 0.1, selection);
     assert.equal(selection.length, 1);
-    assert.instanceOf(selection[0], tv.c.trace_model.ObjectSnapshot);
+    assert.instanceOf(selection[0], tr.model.ObjectSnapshot);
 
     // Hit the instance, between the 1st and 2nd snapshots
     selection = new Selection();
     track.addIntersectingEventsInRangeToSelectionInWorldSpace(
         20, 20.1, 0.1, selection);
     assert.equal(selection.length, 1);
-    assert.instanceOf(selection[0], tv.c.trace_model.ObjectInstance);
+    assert.instanceOf(selection[0], tr.model.ObjectInstance);
   });
 
   test('addEventNearToProvidedEventToSelection', function() {
@@ -95,7 +95,7 @@
     var track = ObjectInstanceTrack(new Viewport());
     track.objectInstances = frames;
 
-    var instance = new tv.c.trace_model.ObjectInstance(
+    var instance = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'n', 10);
 
     assert.doesNotThrow(function() {
diff --git a/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track.html b/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track.html
index 1e59e3d..0c8d19c 100644
--- a/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   var ALLOCATED_MEMORY_TRACK_HEIGHT = 50;
 
@@ -21,14 +21,14 @@
    * @constructor
    * @extends {ContainerTrack}
    */
-  var ProcessMemoryDumpTrack = tv.b.ui.define(
-      'process-memory-dump-track', tv.c.tracks.ContainerTrack);
+  var ProcessMemoryDumpTrack = tr.b.ui.define(
+      'process-memory-dump-track', tr.c.tracks.ContainerTrack);
 
   ProcessMemoryDumpTrack.prototype = {
-    __proto__: tv.c.tracks.ContainerTrack.prototype,
+    __proto__: tr.c.tracks.ContainerTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
       this.memoryDumps_ = undefined;
     },
 
@@ -54,12 +54,12 @@
     },
 
     appendAllocatedMemoryTrack_: function() {
-      var series = tv.c.tracks.buildProcessAllocatedMemoryChartSeries(
+      var series = tr.c.tracks.buildProcessAllocatedMemoryChartSeries(
           this.memoryDumps_);
       if (!series)
         return;
 
-      var track = new tv.c.tracks.ChartTrack(this.viewport);
+      var track = new tr.c.tracks.ChartTrack(this.viewport);
       track.heading = 'Allocated memory (per allocator)';
       track.height = ALLOCATED_MEMORY_TRACK_HEIGHT + 'px';
       track.series = series;
diff --git a/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track_test.html b/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track_test.html
index 33140ac..1b1a121 100644
--- a/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/process_memory_dump_track_test.html
@@ -14,10 +14,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Viewport = tv.c.TimelineViewport;
-  var ProcessMemoryDumpTrack = tv.c.tracks.ProcessMemoryDumpTrack;
-  var createTestProcessMemoryDumps = tv.c.tracks.createTestProcessMemoryDumps;
+tr.b.unittest.testSuite(function() {
+  var Viewport = tr.c.TimelineViewport;
+  var ProcessMemoryDumpTrack = tr.c.tracks.ProcessMemoryDumpTrack;
+  var createTestProcessMemoryDumps = tr.c.tracks.createTestProcessMemoryDumps;
 
   function instantiateTrack(withVMRegions, withAllocatorDumps,
                             expectedTrackCount) {
@@ -25,7 +25,7 @@
 
     var div = document.createElement('div');
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = new ProcessMemoryDumpTrack(viewport);
@@ -38,7 +38,7 @@
     if (expectedTrackCount > 0)
       this.addHTMLOutput(div);
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 50, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
 
diff --git a/trace-viewer/trace_viewer/core/tracks/process_summary_track.html b/trace-viewer/trace_viewer/core/tracks/process_summary_track.html
index 945d010..8192291 100644
--- a/trace-viewer/trace_viewer/core/tracks/process_summary_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/process_summary_track.html
@@ -12,13 +12,13 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * Visualizes a Process's state using a series of rects to represent activity.
    * @constructor
    */
-  var ProcessSummaryTrack = tv.b.ui.define('process-summary-track',
-                                           tv.c.tracks.RectTrack);
+  var ProcessSummaryTrack = tr.b.ui.define('process-summary-track',
+                                           tr.c.tracks.RectTrack);
 
   ProcessSummaryTrack.buildRectsFromProcess = function(process) {
     if (!process)
@@ -57,9 +57,9 @@
      * If an important slice starts in the middle of another,
      * just drop it on the floor.
      */
-    var genericColorId = tv.b.ui.getColorIdForReservedName('generic_work');
+    var genericColorId = tr.b.ui.getColorIdForReservedName('generic_work');
     var pushRect = function(start, end, slice) {
-      rects.push(new tv.c.tracks.Rect(
+      rects.push(new tr.c.tracks.Rect(
           slice, /* modelItem: show selection state of slice if present */
           slice ? slice.title : '', /* title */
           slice ? slice.colorId : genericColorId, /* colorId */
@@ -105,10 +105,10 @@
   };
 
   ProcessSummaryTrack.prototype = {
-    __proto__: tv.c.tracks.RectTrack.prototype,
+    __proto__: tr.c.tracks.RectTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
     },
 
     get process() {
diff --git a/trace-viewer/trace_viewer/core/tracks/process_summary_track_test.html b/trace-viewer/trace_viewer/core/tracks/process_summary_track_test.html
index b682ec6..f022b4c 100644
--- a/trace-viewer/trace_viewer/core/tracks/process_summary_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/process_summary_track_test.html
@@ -6,21 +6,21 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/slice_group.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/tracks/process_summary_track.html">
+<link rel="import" href="/model/slice_group.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ProcessSummaryTrack = tv.c.tracks.ProcessSummaryTrack;
-  var newSlice = tv.c.test_utils.newSlice;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
+tr.b.unittest.testSuite(function() {
+  var ProcessSummaryTrack = tr.c.tracks.ProcessSummaryTrack;
+  var newSlice = tr.c.test_utils.newSlice;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
 
   test('buildRectSimple', function() {
     var process;
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       process = model.getOrCreateProcess(1);
       // XXXX
       //    XXXX
@@ -40,7 +40,7 @@
 
   test('buildRectComplex', function() {
     var process;
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       process = model.getOrCreateProcess(1);
       // XXXX    X X XX
       //    XXXX XXX    X
@@ -70,7 +70,7 @@
 
   test('buildRectImportantSlice', function() {
     var process;
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       //    [    unimportant    ]
       //         [important]
       var a = newSliceNamed('unimportant', 4, 21);
diff --git a/trace-viewer/trace_viewer/core/tracks/process_track.html b/trace-viewer/trace_viewer/core/tracks/process_track.html
index 5737e8e..173a9de 100644
--- a/trace-viewer/trace_viewer/core/tracks/process_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/process_track.html
@@ -12,24 +12,24 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
-  var ProcessTrackBase = tv.c.tracks.ProcessTrackBase;
+tr.exportTo('tr.c.tracks', function() {
+  var ProcessTrackBase = tr.c.tracks.ProcessTrackBase;
 
   /**
    * @constructor
    */
-  var ProcessTrack = tv.b.ui.define('process-track', ProcessTrackBase);
+  var ProcessTrack = tr.b.ui.define('process-track', ProcessTrackBase);
 
   ProcessTrack.prototype = {
     __proto__: ProcessTrackBase.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ProcessTrackBase.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ProcessTrackBase.prototype.decorate.call(this, viewport);
     },
 
     drawTrack: function(type) {
       switch (type) {
-        case tv.c.tracks.DrawType.INSTANT_EVENT:
+        case tr.c.tracks.DrawType.INSTANT_EVENT:
           if (!this.processBase.instantEvents ||
               this.processBase.instantEvents.length === 0)
             break;
@@ -48,7 +48,7 @@
           var viewRWorld = dt.xViewToWorld(
               bounds.width * pixelRatio);
 
-          tv.c.drawInstantSlicesAsLines(
+          tr.c.drawInstantSlicesAsLines(
               ctx,
               this.viewport.currentDisplayTransform,
               viewLWorld,
@@ -61,14 +61,14 @@
 
           break;
 
-        case tv.c.tracks.DrawType.BACKGROUND:
+        case tr.c.tracks.DrawType.BACKGROUND:
           this.drawBackground_();
           // Don't bother recursing further, Process is the only level that
           // draws backgrounds.
           return;
       }
 
-      tv.c.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
+      tr.c.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
     },
 
     drawBackground_: function() {
@@ -79,8 +79,8 @@
       var draw = false;
       ctx.fillStyle = '#eee';
       for (var i = 0; i < this.children.length; ++i) {
-        if (!(this.children[i] instanceof tv.c.tracks.Track) ||
-            (this.children[i] instanceof tv.c.tracks.SpacingTrack))
+        if (!(this.children[i] instanceof tr.c.tracks.Track) ||
+            (this.children[i] instanceof tr.c.tracks.SpacingTrack))
           continue;
 
         draw = !draw;
@@ -116,7 +116,7 @@
     appendMemoryDumpTrack_: function() {
       var processMemoryDumps = this.process.memoryDumps;
       if (processMemoryDumps.length) {
-        var pmdt = new tv.c.tracks.ProcessMemoryDumpTrack(this.viewport_);
+        var pmdt = new tr.c.tracks.ProcessMemoryDumpTrack(this.viewport_);
         pmdt.memoryDumps = processMemoryDumps;
         this.appendChild(pmdt);
       }
@@ -127,13 +127,13 @@
       function onPickHit(instantEvent) {
         selection.push(instantEvent);
       }
-      tv.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,
+      tr.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,
           function(x) { return x.start; },
           function(x) { return x.duration; },
           loWX, hiWX,
           onPickHit.bind(this));
 
-      tv.c.tracks.ContainerTrack.prototype.
+      tr.c.tracks.ContainerTrack.prototype.
           addIntersectingEventsInRangeToSelectionInWorldSpace.
           apply(this, arguments);
     },
@@ -142,7 +142,7 @@
                                          selection) {
       this.addClosestInstantEventToSelection(this.processBase.instantEvents,
                                              worldX, worldMaxDist, selection);
-      tv.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.
+      tr.c.tracks.ContainerTrack.prototype.addClosestEventToSelection.
           apply(this, arguments);
     }
   };
diff --git a/trace-viewer/trace_viewer/core/tracks/process_track_base.html b/trace-viewer/trace_viewer/core/tracks/process_track_base.html
index 423da55..f4f2551 100644
--- a/trace-viewer/trace_viewer/core/tracks/process_track_base.html
+++ b/trace-viewer/trace_viewer/core/tracks/process_track_base.html
@@ -14,44 +14,43 @@
 <link rel="import" href="/core/tracks/process_summary_track.html">
 <link rel="import" href="/core/tracks/spacing_track.html">
 <link rel="import" href="/core/tracks/thread_track.html">
-<link rel="import" href="/core/trace_model/trace_model_settings.html">
 <link rel="import" href="/core/filter.html">
 <link rel="import" href="/base/ui.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
+<link rel="import" href="/model/model_settings.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
-  var ObjectSnapshotView = tv.c.analysis.ObjectSnapshotView;
-  var ObjectInstanceView = tv.c.analysis.ObjectInstanceView;
-  var TraceModelSettings = tv.c.TraceModelSettings;
-  var SpacingTrack = tv.c.tracks.SpacingTrack;
+  var ObjectSnapshotView = tr.c.analysis.ObjectSnapshotView;
+  var ObjectInstanceView = tr.c.analysis.ObjectInstanceView;
+  var SpacingTrack = tr.c.tracks.SpacingTrack;
 
   /**
    * Visualizes a Process by building ThreadTracks and CounterTracks.
    * @constructor
    */
   var ProcessTrackBase =
-      tv.b.ui.define('process-track-base', tv.c.tracks.ContainerTrack);
+      tr.b.ui.define('process-track-base', tr.c.tracks.ContainerTrack);
 
   ProcessTrackBase.prototype = {
 
-    __proto__: tv.c.tracks.ContainerTrack.prototype,
+    __proto__: tr.c.tracks.ContainerTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
 
       this.processBase_ = undefined;
 
       this.classList.add('process-track-base');
       this.classList.add('expanded');
 
-      this.processNameEl_ = tv.b.ui.createSpan();
+      this.processNameEl_ = tr.b.ui.createSpan();
       this.processNameEl_.classList.add('process-track-name');
 
-      this.headerEl_ = tv.b.ui.createDiv({className: 'process-track-header'});
+      this.headerEl_ = tr.b.ui.createDiv({className: 'process-track-header'});
       this.headerEl_.appendChild(this.processNameEl_);
       this.headerEl_.addEventListener('click', this.onHeaderClick_.bind(this));
 
@@ -66,7 +65,7 @@
       this.processBase_ = processBase;
 
       if (this.processBase_) {
-        var modelSettings = new TraceModelSettings(this.processBase_.model);
+        var modelSettings = new tr.model.ModelSettings(this.processBase_.model);
         var defaultValue = this.processBase_.important;
         this.expanded = modelSettings.getSettingFor(
             this.processBase_, 'expanded', defaultValue);
@@ -95,7 +94,7 @@
       if (!this.processBase_)
         return;
 
-      var modelSettings = new TraceModelSettings(this.processBase_.model);
+      var modelSettings = new tr.model.ModelSettings(this.processBase_.model);
       modelSettings.setSettingFor(this.processBase_, 'expanded', expanded);
       this.updateContents_();
       this.viewport.rebuildEventToTrackMap();
@@ -155,7 +154,7 @@
     },
 
     appendSummaryTrack_: function() {
-      var track = new tv.c.tracks.ProcessSummaryTrack(this.viewport);
+      var track = new tr.c.tracks.ProcessSummaryTrack(this.viewport);
       track.process = this.process;
       if (!track.hasVisibleContent)
         return;
@@ -168,7 +167,7 @@
       if (!frames || !frames.length)
         return;
 
-      var track = new tv.c.tracks.FrameTrack(this.viewport);
+      var track = new tr.c.tracks.FrameTrack(this.viewport);
       track.frames = frames;
       this.appendChild(track);
       this.backgroundProvider = track;
@@ -177,7 +176,7 @@
     appendObjectInstanceTracks_: function() {
       var instancesByTypeName =
           this.processBase_.objects.getAllInstancesByTypeName();
-      var instanceTypeNames = tv.b.dictionaryKeys(instancesByTypeName);
+      var instanceTypeNames = tr.b.dictionaryKeys(instancesByTypeName);
       instanceTypeNames.sort();
 
       var didAppendAtLeastOneTrack = false;
@@ -219,15 +218,15 @@
         // Look up the constructor for this track, or use the default
         // constructor if none exists.
         var trackConstructor =
-            tv.c.tracks.ObjectInstanceTrack.getConstructor(
+            tr.c.tracks.ObjectInstanceTrack.getConstructor(
                 undefined, typeName);
         if (!trackConstructor) {
           var snapshotViewInfo = ObjectSnapshotView.getTypeInfo(
               undefined, typeName);
           if (snapshotViewInfo && snapshotViewInfo.metadata.showInstances) {
-            trackConstructor = tv.c.tracks.ObjectInstanceGroupTrack;
+            trackConstructor = tr.c.tracks.ObjectInstanceGroupTrack;
           } else {
-            trackConstructor = tv.c.tracks.ObjectInstanceTrack;
+            trackConstructor = tr.c.tracks.ObjectInstanceTrack;
           }
         }
         var track = new trackConstructor(this.viewport);
@@ -241,12 +240,12 @@
 
     appendCounterTracks_: function() {
       // Add counter tracks for this process.
-      var counters = tv.b.dictionaryValues(this.processBase.counters);
-      counters.sort(tv.c.trace_model.Counter.compare);
+      var counters = tr.b.dictionaryValues(this.processBase.counters);
+      counters.sort(tr.model.Counter.compare);
 
       // Create the counters for this process.
       counters.forEach(function(counter) {
-        var track = new tv.c.tracks.CounterTrack(this.viewport);
+        var track = new tr.c.tracks.CounterTrack(this.viewport);
         track.counter = counter;
         this.appendChild(track);
         this.appendChild(new SpacingTrack(this.viewport));
@@ -255,12 +254,12 @@
 
     appendThreadTracks_: function() {
       // Get a sorted list of threads.
-      var threads = tv.b.dictionaryValues(this.processBase.threads);
-      threads.sort(tv.c.trace_model.Thread.compare);
+      var threads = tr.b.dictionaryValues(this.processBase.threads);
+      threads.sort(tr.model.Thread.compare);
 
       // Create the threads.
       threads.forEach(function(thread) {
-        var track = new tv.c.tracks.ThreadTrack(this.viewport);
+        var track = new tr.c.tracks.ThreadTrack(this.viewport);
         track.thread = thread;
         if (!track.hasVisibleContent)
           return;
diff --git a/trace-viewer/trace_viewer/core/tracks/rect_annotation_view.html b/trace-viewer/trace_viewer/core/tracks/rect_annotation_view.html
index e28b98b..3d3fea2 100644
--- a/trace-viewer/trace_viewer/core/tracks/rect_annotation_view.html
+++ b/trace-viewer/trace_viewer/core/tracks/rect_annotation_view.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.annotations', function() {
+tr.exportTo('tr.c.annotations', function() {
   /**
    * A view responsible for drawing a single highlight rectangle box on
    * the timeline.
@@ -23,7 +23,7 @@
   }
 
   RectAnnotationView.prototype = {
-    __proto__: tv.c.annotations.AnnotationView.prototype,
+    __proto__: tr.c.annotations.AnnotationView.prototype,
 
     draw: function(ctx) {
       var dt = this.viewport_.currentDisplayTransform;
diff --git a/trace-viewer/trace_viewer/core/tracks/rect_track.html b/trace-viewer/trace_viewer/core/tracks/rect_track.html
index 9b87b08..64a7207 100644
--- a/trace-viewer/trace_viewer/core/tracks/rect_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/rect_track.html
@@ -7,7 +7,7 @@
 
 <link rel="stylesheet" href="/core/tracks/rect_track.css">
 
-<link rel="import" href="/core/trace_model/proxy_selectable_item.html">
+<link rel="import" href="/model/proxy_selectable_item.html">
 <link rel="import" href="/core/tracks/heading_track.html">
 <link rel="import" href="/core/fast_rect_renderer.html">
 <link rel="import" href="/core/draw_helpers.html">
@@ -17,22 +17,22 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
 
   /**
    * A track that displays an array of Rect objects.
    * @constructor
    * @extends {HeadingTrack}
    */
-  var RectTrack = tv.b.ui.define(
-      'rect-track', tv.c.tracks.HeadingTrack);
+  var RectTrack = tr.b.ui.define(
+      'rect-track', tr.c.tracks.HeadingTrack);
 
   RectTrack.prototype = {
 
-    __proto__: tv.c.tracks.HeadingTrack.prototype,
+    __proto__: tr.c.tracks.HeadingTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
       this.classList.add('rect-track');
       this.asyncStyle_ = false;
       this.rects_ = null;
@@ -70,7 +70,7 @@
 
     draw: function(type, viewLWorld, viewRWorld) {
       switch (type) {
-        case tv.c.tracks.DrawType.GENERAL_EVENT:
+        case tr.c.tracks.DrawType.GENERAL_EVENT:
           this.drawRects_(viewLWorld, viewRWorld);
           break;
       }
@@ -81,7 +81,7 @@
 
       ctx.save();
       var bounds = this.getBoundingClientRect();
-      tv.c.drawSlices(
+      tr.c.drawSlices(
           ctx,
           this.viewport.currentDisplayTransform,
           viewLWorld,
@@ -102,7 +102,7 @@
         fontSize = 10;
         yOffset = 2.5;
       }
-      tv.c.drawLabels(
+      tr.c.drawLabels(
           ctx,
           this.viewport.currentDisplayTransform,
           viewLWorld,
@@ -128,7 +128,7 @@
         rect.addToSelection(selection);
       }
       onRect = onRect.bind(this);
-      tv.b.iterateOverIntersectingIntervals(this.rects_,
+      tr.b.iterateOverIntersectingIntervals(this.rects_,
           function(x) { return x.start; },
           function(x) { return x.duration; },
           loWX, hiWX,
@@ -146,7 +146,7 @@
      * @private
      */
     addEventNearToProvidedEventToSelection: function(event, offset, selection) {
-      var index = tv.b.findFirstIndexInArray(this.rects_, function(rect) {
+      var index = tr.b.findFirstIndexInArray(this.rects_, function(rect) {
         return rect.modelItem === event;
       });
       if (index === -1)
@@ -175,7 +175,7 @@
 
     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
                                          selection) {
-      var rect = tv.b.findClosestIntervalInSortedIntervals(
+      var rect = tr.b.findClosestIntervalInSortedIntervals(
           this.rects_,
           function(x) { return x.start; },
           function(x) { return x.end; },
@@ -196,7 +196,7 @@
    * @extends {ProxySelectableItem}
    */
   function Rect(modelItem, title, colorId, start, duration) {
-    tv.c.trace_model.ProxySelectableItem.call(this, modelItem);
+    tr.model.ProxySelectableItem.call(this, modelItem);
     this.title = title;
     this.colorId = colorId;
     this.start = start;
@@ -205,7 +205,7 @@
   };
 
   Rect.prototype = {
-    __proto__: tv.c.trace_model.ProxySelectableItem.prototype
+    __proto__: tr.model.ProxySelectableItem.prototype
   };
 
   return {
diff --git a/trace-viewer/trace_viewer/core/tracks/rect_track_test.html b/trace-viewer/trace_viewer/core/tracks/rect_track_test.html
index 0959e38..f6f13e1 100644
--- a/trace-viewer/trace_viewer/core/tracks/rect_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/rect_track_test.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/slice.html">
+<link rel="import" href="/model/slice.html">
 <link rel="import" href="/core/timeline_track_view.html">
 <link rel="import" href="/core/draw_helpers.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
@@ -14,18 +14,18 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var RectTrack = tv.c.tracks.RectTrack;
-  var Rect = tv.c.tracks.Rect;
-  var Slice = tv.c.trace_model.Slice;
-  var Viewport = tv.c.TimelineViewport;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var RectTrack = tr.c.tracks.RectTrack;
+  var Rect = tr.c.tracks.Rect;
+  var Slice = tr.model.Slice;
+  var Viewport = tr.c.TimelineViewport;
 
   test('instantiate_withRects', function() {
     var div = document.createElement('div');
 
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = RectTrack(viewport);
@@ -42,7 +42,7 @@
       new Rect(undefined, 'c', 2, 7.6, 0.4)
     ];
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 8.8, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
@@ -51,7 +51,7 @@
     var div = document.createElement('div');
 
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = RectTrack(viewport);
@@ -68,7 +68,7 @@
       new Slice('', 'c', 2, 7.6, {}, 0.4)
     ];
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 8.8, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
@@ -77,7 +77,7 @@
     var div = document.createElement('div');
 
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = RectTrack(viewport);
@@ -96,7 +96,7 @@
       slices.push(s);
     }
     track.rects = slices;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 1.1 * x, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
@@ -116,7 +116,7 @@
       div.appendChild(document.createTextNode(dict.trackName));
 
       var viewport = new Viewport(div);
-      var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+      var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
       div.appendChild(drawingContainer);
 
       var track = new RectTrack(viewport);
@@ -134,14 +134,14 @@
         new Rect(undefined, 'cccc cccc cccc', 1, 7, 0.5),
         new Rect(undefined, 'd', 2, 7.6, 1.0)
       ];
-      var dt = new tv.c.TimelineDisplayTransform();
+      var dt = new tr.c.TimelineDisplayTransform();
       dt.xSetWorldBounds(0, 9.5, track.clientWidth);
       track.viewport.setDisplayTransformImmediately(dt);
     }
   });
 
   test('findAllObjectsMatchingInRectTrack', function() {
-    var track = new RectTrack(new tv.c.TimelineViewport());
+    var track = new RectTrack(new tr.c.TimelineViewport());
     track.rects = [
       new Slice('', 'a', 0, 1, {}, 1),
       new Slice('', 'b', 1, 2.1, {}, 4.8),
@@ -150,7 +150,7 @@
     ];
     var selection = new Selection();
     track.addAllEventsMatchingFilterToSelection(
-        new tv.c.TitleOrCategoryFilter('b'), selection);
+        new tr.c.TitleOrCategoryFilter('b'), selection);
 
     assert.equal(2, selection.length);
     assert.equal(track.rects[1].modelItem, selection[0]);
@@ -159,11 +159,11 @@
 
   test('selectionHitTesting', function() {
     var testEl = document.createElement('div');
-    testEl.appendChild(tv.b.ui.createScopedStyle('heading { width: 100px; }'));
+    testEl.appendChild(tr.b.ui.createScopedStyle('heading { width: 100px; }'));
     testEl.style.width = '600px';
 
     var viewport = new Viewport(testEl);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     testEl.appendChild(drawingContainer);
 
     var track = new RectTrack(viewport);
@@ -182,7 +182,7 @@
     var wW = 10;
     var vW = drawingContainer.canvas.getBoundingClientRect().width;
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, wW, vW * pixelRatio);
     track.viewport.setDisplayTransformImmediately(dt);
 
@@ -215,7 +215,7 @@
     var testEl = document.createElement('div');
 
     var viewport = new Viewport(testEl);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     testEl.appendChild(drawingContainer);
 
     var track = new RectTrack(viewport);
@@ -233,7 +233,7 @@
       new Slice('', bigtitle, 0, 1, {}, 1),
       new Slice('', smalltitle, 1, 2, {}, 1)
     ];
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 3.3, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
 
@@ -242,11 +242,11 @@
 
     // Small titles on big slices are not elided.
     stringWidthPair =
-        tv.c.elidedTitleCache_.get(
+        tr.c.elidedTitleCache_.get(
             track.context(),
             pixWidth,
             smalltitle,
-            tv.c.elidedTitleCache_.labelWidth(
+            tr.c.elidedTitleCache_.labelWidth(
                 track.context(),
                 smalltitle),
             1);
@@ -256,11 +256,11 @@
     var elidedWhenSmallEnough = false;
     for (var sliceLength = 1; sliceLength >= 0.00001; sliceLength /= 2.0) {
       stringWidthPair =
-          tv.c.elidedTitleCache_.get(
+          tr.c.elidedTitleCache_.get(
               track.context(),
               pixWidth,
               smalltitle,
-              tv.c.elidedTitleCache_.labelWidth(
+              tr.c.elidedTitleCache_.labelWidth(
                   track.context(),
                   smalltitle),
               sliceLength);
@@ -277,11 +277,11 @@
       superBigTitle += bigtitle;
     }
     stringWidthPair =
-        tv.c.elidedTitleCache_.get(
+        tr.c.elidedTitleCache_.get(
             track.context(),
             pixWidth,
             superBigTitle,
-            tv.c.elidedTitleCache_.labelWidth(
+            tr.c.elidedTitleCache_.labelWidth(
                 track.context(),
                 superBigTitle),
             1);
@@ -293,7 +293,7 @@
   });
 
   test('rectTrackAddItemNearToProvidedEvent', function() {
-    var track = new RectTrack(new tv.c.TimelineViewport());
+    var track = new RectTrack(new tr.c.TimelineViewport());
     track.rects = [
       new Slice('', 'a', 0, 1, {}, 1),
       new Slice('', 'b', 1, 2.1, {}, 4.8),
@@ -302,7 +302,7 @@
     ];
     var sel = new Selection();
     track.addAllEventsMatchingFilterToSelection(
-        new tv.c.TitleOrCategoryFilter('b'), sel);
+        new tr.c.TitleOrCategoryFilter('b'), sel);
     var ret;
 
     // Select to the right of B.
@@ -334,7 +334,7 @@
     // Select A and then select left.
     var sel = new Selection();
     track.addAllEventsMatchingFilterToSelection(
-        new tv.c.TitleOrCategoryFilter('a'), sel);
+        new tr.c.TitleOrCategoryFilter('a'), sel);
     var ret;
 
     selNone = new Selection();
@@ -344,7 +344,7 @@
   });
 
   test('rectTrackAddClosestEventToSelection', function() {
-    var track = new RectTrack(new tv.c.TimelineViewport());
+    var track = new RectTrack(new tr.c.TimelineViewport());
     track.rects = [
       new Slice('', 'a', 0, 1, {}, 1),
       new Slice('', 'b', 1, 2.1, {}, 4.8),
diff --git a/trace-viewer/trace_viewer/core/tracks/ruler_track.html b/trace-viewer/trace_viewer/core/tracks/ruler_track.html
index f8fe40e..a0d6adf 100644
--- a/trace-viewer/trace_viewer/core/tracks/ruler_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/ruler_track.html
@@ -16,13 +16,13 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays the ruler.
    * @constructor
    * @extends {HeadingTrack}
    */
-  var RulerTrack = tv.b.ui.define('ruler-track', tv.c.tracks.HeadingTrack);
+  var RulerTrack = tr.b.ui.define('ruler-track', tr.c.tracks.HeadingTrack);
 
   var logOf10 = Math.log(10);
   function log10(x) {
@@ -30,10 +30,10 @@
   }
 
   RulerTrack.prototype = {
-    __proto__: tv.c.tracks.HeadingTrack.prototype,
+    __proto__: tr.c.tracks.HeadingTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
       this.classList.add('ruler-track');
       this.strings_secs_ = [];
       this.strings_msecs_ = [];
@@ -46,7 +46,7 @@
     },
 
     detach: function() {
-      tv.c.tracks.HeadingTrack.prototype.detach.call(this);
+      tr.c.tracks.HeadingTrack.prototype.detach.call(this);
       this.viewport.removeEventListener('change',
                                         this.viewportChange_);
     },
@@ -60,10 +60,10 @@
 
     draw: function(type, viewLWorld, viewRWorld) {
       switch (type) {
-        case tv.c.tracks.DrawType.GRID:
+        case tr.c.tracks.DrawType.GRID:
           this.drawGrid_(viewLWorld, viewRWorld);
           break;
-        case tv.c.tracks.DrawType.MARKERS:
+        case tr.c.tracks.DrawType.MARKERS:
           if (!this.viewport.interestRange.isEmpty)
             this.viewport.interestRange.draw(this.context(),
                                              viewLWorld, viewRWorld);
@@ -182,12 +182,12 @@
         vp.majorMarkPositions.push(curXView);
 
         // Major mark
-        tv.c.drawLine(ctx, curXView, 0, curXView, rulerHeight);
+        tr.c.drawLine(ctx, curXView, 0, curXView, rulerHeight);
 
         // Minor marks
         for (var i = 1; i < numTicksPerMajor; ++i) {
           var xView = Math.floor(curXView + minorMarkDistancePx * i);
-          tv.c.drawLine(ctx,
+          tr.c.drawLine(ctx,
               xView, rulerHeight - minorTickH,
               xView, rulerHeight);
         }
@@ -195,7 +195,7 @@
 
       // Draw bottom bar.
       ctx.strokeStyle = 'rgb(0, 0, 0)';
-      tv.c.drawLine(ctx, 0, height, width, height);
+      tr.c.drawLine(ctx, 0, height, width, height);
       ctx.stroke();
 
       // Give distance between directly adjacent markers.
@@ -203,7 +203,7 @@
         return;
 
       // Draw middle bar.
-      tv.c.drawLine(ctx, 0, rulerHeight, width, rulerHeight);
+      tr.c.drawLine(ctx, 0, rulerHeight, width, rulerHeight);
       ctx.stroke();
 
       // Distance Variables.
@@ -298,16 +298,16 @@
         // Draw the arrows pointing from outside in and a line in between.
         ctx.strokeStyle = arrowColor;
         ctx.beginPath();
-        tv.c.drawLine(ctx, leftMarkerView, arrowPosY, rightMarkerView,
+        tr.c.drawLine(ctx, leftMarkerView, arrowPosY, rightMarkerView,
             arrowPosY);
         ctx.stroke();
 
         ctx.fillStyle = arrowColor;
-        tv.c.drawArrow(ctx,
+        tr.c.drawArrow(ctx,
             leftMarkerView - 1.5 * arrowSpacing, arrowPosY,
             leftMarkerView, arrowPosY,
             arrowLengthView, arrowWidthView);
-        tv.c.drawArrow(ctx,
+        tr.c.drawArrow(ctx,
             rightMarkerView + 1.5 * arrowSpacing, arrowPosY,
             rightMarkerView, arrowPosY,
             arrowLengthView, arrowWidthView);
@@ -330,11 +330,11 @@
         // Draw the arrows pointing inside out.
         ctx.strokeStyle = arrowColor;
         ctx.fillStyle = arrowColor;
-        tv.c.drawArrow(ctx,
+        tr.c.drawArrow(ctx,
             leftArrowStart, arrowPosY,
             leftMarkerView, arrowPosY,
             arrowLengthView, arrowWidthView);
-        tv.c.drawArrow(ctx,
+        tr.c.drawArrow(ctx,
             rightArrowStart, arrowPosY,
             rightMarkerView, arrowPosY,
             arrowLengthView, arrowWidthView);
diff --git a/trace-viewer/trace_viewer/core/tracks/ruler_track_test.html b/trace-viewer/trace_viewer/core/tracks/ruler_track_test.html
index d44c8a6..e469c23 100644
--- a/trace-viewer/trace_viewer/core/tracks/ruler_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/ruler_track_test.html
@@ -13,21 +13,21 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
     var div = document.createElement('div');
 
-    var viewport = new tv.c.TimelineViewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var viewport = new tr.c.TimelineViewport(div);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
-    var track = tv.c.tracks.RulerTrack(viewport);
+    var track = tr.c.tracks.RulerTrack(viewport);
     drawingContainer.appendChild(track);
     this.addHTMLOutput(div);
 
     drawingContainer.invalidate();
 
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.setPanAndScale(0, track.clientWidth / 1000);
     track.viewport.setDisplayTransformImmediately(dt);
   });
diff --git a/trace-viewer/trace_viewer/core/tracks/sample_track.html b/trace-viewer/trace_viewer/core/tracks/sample_track.html
index 9d81e4e..52c83a1 100644
--- a/trace-viewer/trace_viewer/core/tracks/sample_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/sample_track.html
@@ -10,21 +10,21 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays an array of Sample objects.
    * @constructor
    * @extends {HeadingTrack}
    */
-  var SampleTrack = tv.b.ui.define(
-      'sample-track', tv.c.tracks.RectTrack);
+  var SampleTrack = tr.b.ui.define(
+      'sample-track', tr.c.tracks.RectTrack);
 
   SampleTrack.prototype = {
 
-    __proto__: tv.c.tracks.RectTrack.prototype,
+    __proto__: tr.c.tracks.RectTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
     },
 
     get samples() {
diff --git a/trace-viewer/trace_viewer/core/tracks/sample_track_test.html b/trace-viewer/trace_viewer/core/tracks/sample_track_test.html
index 971ac82..fd8e573 100644
--- a/trace-viewer/trace_viewer/core/tracks/sample_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/sample_track_test.html
@@ -7,21 +7,21 @@
 
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/timeline_track_view.html">
-<link rel="import" href="/core/trace_model/sample.html">
-<link rel="import" href="/core/trace_model/stack_frame.html">
+<link rel="import" href="/model/sample.html">
+<link rel="import" href="/model/stack_frame.html">
 <link rel="import" href="/core/tracks/sample_track.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var SampleTrack = tv.c.tracks.SampleTrack;
-  var Sample = tv.c.trace_model.Sample;
-  var StackFrame = tv.c.trace_model.StackFrame;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var SampleTrack = tr.c.tracks.SampleTrack;
+  var Sample = tr.model.Sample;
+  var StackFrame = tr.model.StackFrame;
 
   test('modelMapping', function() {
-    var track = new SampleTrack(new tv.c.TimelineViewport());
+    var track = new SampleTrack(new tr.c.TimelineViewport());
     var fA = new StackFrame(undefined, 1, 'cat', 'a', 7);
     var sample = new Sample(undefined, undefined, 'instructions_retired',
                             10, fA, 10);
diff --git a/trace-viewer/trace_viewer/core/tracks/slice_group_track.html b/trace-viewer/trace_viewer/core/tracks/slice_group_track.html
index 7c6ab7a..0799176 100644
--- a/trace-viewer/trace_viewer/core/tracks/slice_group_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/slice_group_track.html
@@ -12,21 +12,21 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays a SliceGroup.
    * @constructor
    * @extends {MultiRowTrack}
    */
-  var SliceGroupTrack = tv.b.ui.define(
-      'slice-group-track', tv.c.tracks.MultiRowTrack);
+  var SliceGroupTrack = tr.b.ui.define(
+      'slice-group-track', tr.c.tracks.MultiRowTrack);
 
   SliceGroupTrack.prototype = {
 
-    __proto__: tv.c.tracks.MultiRowTrack.prototype,
+    __proto__: tr.c.tracks.MultiRowTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
       this.classList.add('slice-group-track');
       this.group_ = undefined;
       // Set the collapse threshold so we don't collapse by default, but the
@@ -35,7 +35,7 @@
     },
 
     addSubTrack_: function(slices) {
-      var track = new tv.c.tracks.SliceTrack(this.viewport);
+      var track = new tr.c.tracks.SliceTrack(this.viewport);
       track.slices = slices;
       this.appendChild(track);
       return track;
diff --git a/trace-viewer/trace_viewer/core/tracks/slice_group_track_test.html b/trace-viewer/trace_viewer/core/tracks/slice_group_track_test.html
index e9d0587..0df89bd 100644
--- a/trace-viewer/trace_viewer/core/tracks/slice_group_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/slice_group_track_test.html
@@ -7,26 +7,26 @@
 
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_track_view.html">
-<link rel="import" href="/core/trace_model/slice_group.html">
+<link rel="import" href="/model/slice_group.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ProcessTrack = tv.c.tracks.ProcessTrack;
-  var ThreadTrack = tv.c.tracks.ThreadTrack;
-  var SliceGroup = tv.c.trace_model.SliceGroup;
-  var SliceGroupTrack = tv.c.tracks.SliceGroupTrack;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
+tr.b.unittest.testSuite(function() {
+  var ProcessTrack = tr.c.tracks.ProcessTrack;
+  var ThreadTrack = tr.c.tracks.ThreadTrack;
+  var SliceGroup = tr.model.SliceGroup;
+  var SliceGroupTrack = tr.c.tracks.SliceGroupTrack;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
 
   test('subRowBuilderBasic', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
     var sA = group.pushSlice(newSliceNamed('a', 1, 2));
     var sB = group.pushSlice(newSliceNamed('a', 3, 1));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -37,13 +37,13 @@
   });
 
   test('subRowBuilderBasic2', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
     var sA = group.pushSlice(newSliceNamed('a', 1, 4));
     var sB = group.pushSlice(newSliceNamed('b', 3, 1));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -56,14 +56,14 @@
   });
 
   test('subRowBuilderNestedExactly', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
     var sB = group.pushSlice(newSliceNamed('b', 1, 4));
     var sA = group.pushSlice(newSliceNamed('a', 1, 4));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -76,14 +76,14 @@
   });
 
   test('subRowBuilderInstantEvents', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
     var sA = group.pushSlice(newSliceNamed('a', 1, 0));
     var sB = group.pushSlice(newSliceNamed('b', 2, 0));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -94,14 +94,14 @@
   });
 
   test('subRowBuilderTwoInstantEvents', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
     var sA = group.pushSlice(newSliceNamed('a', 1, 0));
     var sB = group.pushSlice(newSliceNamed('b', 1, 0));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -112,7 +112,7 @@
   });
 
   test('subRowBuilderOutOfOrderAddition', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
@@ -122,7 +122,7 @@
     var sB = group.pushSlice(newSliceNamed('b', 3, 1));
     var sA = group.pushSlice(newSliceNamed('a', 1, 2));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -133,7 +133,7 @@
   });
 
   test('subRowBuilderOutOfOrderAddition2', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
@@ -144,7 +144,7 @@
     var sB = group.pushSlice(newSliceNamed('b', 3, 1));
     var sA = group.pushSlice(newSliceNamed('a', 1, 5));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -157,7 +157,7 @@
   });
 
   test('subRowBuilderOnNestedZeroLength', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
@@ -168,7 +168,7 @@
     var sB1 = group.pushSlice(newSliceNamed('b1', 1, 2));
     var sB2 = group.pushSlice(newSliceNamed('b2', 4, 0));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -179,7 +179,7 @@
   });
 
   test('subRowBuilderOnGroup1', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
@@ -190,7 +190,7 @@
     var sB = group.pushSlice(newSliceNamed('b', 1.5, 1));
     var sC = group.pushSlice(newSliceNamed('c', 5, 0));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
     var subRows = track.subRows;
 
@@ -201,7 +201,7 @@
   });
 
   test('subRowBuilderOnGroup2', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
@@ -214,7 +214,7 @@
     var sC = group.pushSlice(newSliceNamed('c', 1.75, 0.5));
     var sD = group.pushSlice(newSliceNamed('c', 5, 0.25));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
 
     var subRows = track.subRows;
@@ -226,14 +226,14 @@
   });
 
   test('trackFiltering', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
     var group = t1.sliceGroup;
 
     var sA = group.pushSlice(newSliceNamed('a', 1, 3));
     var sB = group.pushSlice(newSliceNamed('b', 1.5, 1));
 
-    var track = new SliceGroupTrack(new tv.c.TimelineViewport());
+    var track = new SliceGroupTrack(new tr.c.TimelineViewport());
     track.group = group;
 
     assert.equal(track.subRows.length, 2);
@@ -241,9 +241,9 @@
   });
 
 test('sliceGroupContainerMap', function() {
-    var vp = new tv.c.TimelineViewport();
+    var vp = new tr.c.TimelineViewport();
     var containerToTrack = vp.containerToTrackObj;
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var process = model.getOrCreateProcess(123);
     var thread = process.getOrCreateThread(456);
     var group = new SliceGroup(thread);
diff --git a/trace-viewer/trace_viewer/core/tracks/slice_track.html b/trace-viewer/trace_viewer/core/tracks/slice_track.html
index 0d40c3e..0109ada 100644
--- a/trace-viewer/trace_viewer/core/tracks/slice_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/slice_track.html
@@ -10,21 +10,21 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays an array of Slice objects.
    * @constructor
    * @extends {HeadingTrack}
    */
-  var SliceTrack = tv.b.ui.define(
-      'slice-track', tv.c.tracks.RectTrack);
+  var SliceTrack = tr.b.ui.define(
+      'slice-track', tr.c.tracks.RectTrack);
 
   SliceTrack.prototype = {
 
-    __proto__: tv.c.tracks.RectTrack.prototype,
+    __proto__: tr.c.tracks.RectTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
     },
 
     get slices() {
diff --git a/trace-viewer/trace_viewer/core/tracks/slice_track_test.html b/trace-viewer/trace_viewer/core/tracks/slice_track_test.html
index 8e01895..40e2e01 100644
--- a/trace-viewer/trace_viewer/core/tracks/slice_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/slice_track_test.html
@@ -7,19 +7,19 @@
 
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/timeline_track_view.html">
-<link rel="import" href="/core/trace_model/slice.html">
+<link rel="import" href="/model/slice.html">
 <link rel="import" href="/core/tracks/slice_track.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Selection = tv.c.Selection;
-  var SliceTrack = tv.c.tracks.SliceTrack;
-  var Slice = tv.c.trace_model.Slice;
+tr.b.unittest.testSuite(function() {
+  var Selection = tr.c.Selection;
+  var SliceTrack = tr.c.tracks.SliceTrack;
+  var Slice = tr.model.Slice;
 
   test('modelMapping', function() {
-    var track = new SliceTrack(new tv.c.TimelineViewport());
+    var track = new SliceTrack(new tr.c.TimelineViewport());
     var slice = new Slice('', 'a', 0, 1, {}, 1);
     track.slices = [slice];
     var me0 = track.rects[0].modelItem;
diff --git a/trace-viewer/trace_viewer/core/tracks/spacing_track.html b/trace-viewer/trace_viewer/core/tracks/spacing_track.html
index 049a81e..1ea4f21 100644
--- a/trace-viewer/trace_viewer/core/tracks/spacing_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/spacing_track.html
@@ -12,18 +12,18 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * @constructor
    */
-  var SpacingTrack = tv.b.ui.define('spacing-track',
-                                    tv.c.tracks.HeadingTrack);
+  var SpacingTrack = tr.b.ui.define('spacing-track',
+                                    tr.c.tracks.HeadingTrack);
 
   SpacingTrack.prototype = {
-    __proto__: tv.c.tracks.HeadingTrack.prototype,
+    __proto__: tr.c.tracks.HeadingTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
       this.classList.add('spacing-track');
     },
 
diff --git a/trace-viewer/trace_viewer/core/tracks/stacked_bars_track.html b/trace-viewer/trace_viewer/core/tracks/stacked_bars_track.html
index d2c60f1..5b2158c 100644
--- a/trace-viewer/trace_viewer/core/tracks/stacked_bars_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/stacked_bars_track.html
@@ -11,21 +11,21 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * A track that displays traces as stacked bars.
    * @constructor
    * @extends {HeadingTrack}
    */
-  var StackedBarsTrack = tv.b.ui.define(
-      'stacked-bars-track', tv.c.tracks.HeadingTrack);
+  var StackedBarsTrack = tr.b.ui.define(
+      'stacked-bars-track', tr.c.tracks.HeadingTrack);
 
   StackedBarsTrack.prototype = {
 
-    __proto__: tv.c.tracks.HeadingTrack.prototype,
+    __proto__: tr.c.tracks.HeadingTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
       this.classList.add('stacked-bars-track');
       this.objectInstance_ = null;
     },
@@ -49,7 +49,7 @@
       var snapshots = this.objectInstance_.snapshots;
       var maxBounds = this.objectInstance_.parent.model.bounds.max;
 
-      tv.b.iterateOverIntersectingIntervals(
+      tr.b.iterateOverIntersectingIntervals(
           snapshots,
           function(x) { return x.ts; },
           function(x, i) {
@@ -77,7 +77,7 @@
      * @private
      */
     addEventNearToProvidedEventToSelection: function(event, offset, selection) {
-      if (!(event instanceof tv.c.trace_model.ObjectSnapshot))
+      if (!(event instanceof tr.model.ObjectSnapshot))
         throw new Error('Unrecognized event');
       var objectSnapshots = this.objectInstance_.snapshots;
       var index = objectSnapshots.indexOf(event);
@@ -94,7 +94,7 @@
 
     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
                                          selection) {
-      var snapshot = tv.b.findClosestElementInSortedArray(
+      var snapshot = tr.b.findClosestElementInSortedArray(
           this.objectInstance_.snapshots,
           function(x) { return x.ts; },
           worldX,
diff --git a/trace-viewer/trace_viewer/core/tracks/thread_track.html b/trace-viewer/trace_viewer/core/tracks/thread_track.html
index 2278c4b..c4165c2 100644
--- a/trace-viewer/trace_viewer/core/tracks/thread_track.html
+++ b/trace-viewer/trace_viewer/core/tracks/thread_track.html
@@ -19,18 +19,18 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * Visualizes a Thread using a series of SliceTracks.
    * @constructor
    */
-  var ThreadTrack = tv.b.ui.define('thread-track',
-                                   tv.c.tracks.ContainerTrack);
+  var ThreadTrack = tr.b.ui.define('thread-track',
+                                   tr.c.tracks.ContainerTrack);
   ThreadTrack.prototype = {
-    __proto__: tv.c.tracks.ContainerTrack.prototype,
+    __proto__: tr.c.tracks.ContainerTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
       this.classList.add('thread-track');
     },
 
@@ -72,16 +72,16 @@
       this.appendThreadSamplesTracks_();
 
       if (this.thread_.timeSlices) {
-        var timeSlicesTrack = new tv.c.tracks.SliceTrack(this.viewport);
+        var timeSlicesTrack = new tr.c.tracks.SliceTrack(this.viewport);
         timeSlicesTrack.heading = '';
-        timeSlicesTrack.height = tv.c.THIN_SLICE_HEIGHT + 'px';
+        timeSlicesTrack.height = tr.c.THIN_SLICE_HEIGHT + 'px';
         timeSlicesTrack.slices = this.thread_.timeSlices;
         if (timeSlicesTrack.hasVisibleContent)
           this.appendChild(timeSlicesTrack);
       }
 
       if (this.thread_.sliceGroup.length) {
-        var track = new tv.c.tracks.SliceGroupTrack(this.viewport);
+        var track = new tr.c.tracks.SliceGroupTrack(this.viewport);
         track.heading = this.thread_.userFriendlyName;
         track.tooltip = this.thread_.userFriendlyDetails;
         track.group = this.thread_.sliceGroup;
@@ -93,7 +93,7 @@
     appendAsyncSliceTracks_: function() {
       var subGroups = this.thread_.asyncSliceGroup.viewSubGroups;
       subGroups.forEach(function(subGroup) {
-        var asyncTrack = new tv.c.tracks.AsyncSliceGroupTrack(this.viewport);
+        var asyncTrack = new tr.c.tracks.AsyncSliceGroupTrack(this.viewport);
         var title = subGroup.slices[0].viewSubGroupTitle;
         asyncTrack.group = subGroup;
         asyncTrack.heading = title;
@@ -113,19 +113,19 @@
         samplesByTitle[sample.title].push(sample);
       });
 
-      var sampleTitles = tv.b.dictionaryKeys(samplesByTitle);
+      var sampleTitles = tr.b.dictionaryKeys(samplesByTitle);
       sampleTitles.sort();
 
       sampleTitles.forEach(function(sampleTitle) {
         var samples = samplesByTitle[sampleTitle];
-        var samplesTrack = new tv.c.tracks.SampleTrack(this.viewport);
+        var samplesTrack = new tr.c.tracks.SampleTrack(this.viewport);
         samplesTrack.group = this.thread_;
         samplesTrack.samples = samples;
         samplesTrack.heading = this.thread_.userFriendlyName + ': ' +
             sampleTitle;
         samplesTrack.tooltip = this.thread_.userFriendlyDetails;
         samplesTrack.selectionGenerator = function() {
-          var selection = new tv.c.Selection();
+          var selection = new tr.c.Selection();
           for (var i = 0; i < samplesTrack.samples.length; i++) {
             selection.push(samplesTrack.samples[i]);
           }
diff --git a/trace-viewer/trace_viewer/core/tracks/thread_track_test.html b/trace-viewer/trace_viewer/core/tracks/thread_track_test.html
index 08bb1e4..0845cbb 100644
--- a/trace-viewer/trace_viewer/core/tracks/thread_track_test.html
+++ b/trace-viewer/trace_viewer/core/tracks/thread_track_test.html
@@ -7,40 +7,40 @@
 
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/timeline_track_view.html">
-<link rel="import" href="/core/trace_model/instant_event.html">
+<link rel="import" href="/model/instant_event.html">
 <link rel="import" href="/core/tracks/thread_track.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var HighlightInstantEvent = tv.c.trace_model.ThreadHighlightInstantEvent;
-  var Process = tv.c.trace_model.Process;
-  var Selection = tv.c.Selection;
-  var StackFrame = tv.c.trace_model.StackFrame;
-  var Sample = tv.c.trace_model.Sample;
-  var Thread = tv.c.trace_model.Thread;
-  var ThreadSlice = tv.c.trace_model.ThreadSlice;
-  var ThreadTrack = tv.c.tracks.ThreadTrack;
-  var Viewport = tv.c.TimelineViewport;
-  var newAsyncSlice = tv.c.test_utils.newAsyncSlice;
-  var newAsyncSliceNamed = tv.c.test_utils.newAsyncSliceNamed;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
+tr.b.unittest.testSuite(function() {
+  var HighlightInstantEvent = tr.model.ThreadHighlightInstantEvent;
+  var Process = tr.model.Process;
+  var Selection = tr.c.Selection;
+  var StackFrame = tr.model.StackFrame;
+  var Sample = tr.model.Sample;
+  var Thread = tr.model.Thread;
+  var ThreadSlice = tr.model.ThreadSlice;
+  var ThreadTrack = tr.c.tracks.ThreadTrack;
+  var Viewport = tr.c.TimelineViewport;
+  var newAsyncSlice = tr.c.test_utils.newAsyncSlice;
+  var newAsyncSliceNamed = tr.c.test_utils.newAsyncSliceNamed;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
 
   test('selectionHitTestingWithThreadTrack', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 4));
     t1.sliceGroup.pushSlice(new ThreadSlice('', 'b', 0, 5.1, {}, 4));
 
     var testEl = document.createElement('div');
-    testEl.appendChild(tv.b.ui.createScopedStyle('heading { width: 100px; }'));
+    testEl.appendChild(tr.b.ui.createScopedStyle('heading { width: 100px; }'));
     testEl.style.width = '600px';
 
     var viewport = new Viewport(testEl);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     testEl.appendChild(drawingContainer);
 
     var track = new ThreadTrack(viewport);
@@ -52,7 +52,7 @@
     var h = track.getBoundingClientRect().height;
     var wW = 10;
     var vW = drawingContainer.canvas.getBoundingClientRect().width;
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, wW, vW);
     track.viewport.setDisplayTransformImmediately(dt);
 
@@ -70,21 +70,21 @@
   });
 
   test('filterThreadSlices', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var thread = new Thread(new Process(model, 7), 1);
     thread.sliceGroup.pushSlice(newSliceNamed('a', 0, 0));
     thread.asyncSliceGroup.push(newAsyncSliceNamed('a', 0, 5, t, t));
 
-    var t = new ThreadTrack(new tv.c.TimelineViewport());
+    var t = new ThreadTrack(new tr.c.TimelineViewport());
     t.thread = thread;
 
     assert.equal(t.tracks_.length, 2);
-    assert.instanceOf(t.tracks_[0], tv.c.tracks.AsyncSliceGroupTrack);
-    assert.instanceOf(t.tracks_[1], tv.c.tracks.SliceGroupTrack);
+    assert.instanceOf(t.tracks_[0], tr.c.tracks.AsyncSliceGroupTrack);
+    assert.instanceOf(t.tracks_[1], tr.c.tracks.SliceGroupTrack);
   });
 
   test('sampleThreadSlices', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var thread;
     var cpu;
     model.importTraces([], false, false, function() {
@@ -115,23 +115,23 @@
                                     35, fAD, 10));
     });
 
-    var t = new ThreadTrack(new tv.c.TimelineViewport());
+    var t = new ThreadTrack(new tr.c.TimelineViewport());
     t.thread = thread;
     assert.equal(t.tracks_.length, 2);
 
     // Instructions retired
     var t0 = t.tracks_[0];
     assert.notEqual(t0.heading.indexOf('instructions_retired'), -1);
-    assert.instanceOf(t0, tv.c.tracks.SampleTrack);
+    assert.instanceOf(t0, tr.c.tracks.SampleTrack);
     assert.equal(t0.samples.length, 4);
     t0.samples.forEach(function(s) {
-      assert.instanceOf(s, tv.c.trace_model.Sample);
+      assert.instanceOf(s, tr.model.Sample);
     });
 
     // page_fault
     var t1 = t.tracks_[1];
     assert.notEqual(t1.heading.indexOf('page_fault'), -1);
-    assert.instanceOf(t1, tv.c.tracks.SampleTrack);
+    assert.instanceOf(t1, tr.c.tracks.SampleTrack);
     assert.equal(t1.samples.length, 2);
   });
 });
diff --git a/trace-viewer/trace_viewer/core/tracks/track.html b/trace-viewer/trace_viewer/core/tracks/track.html
index 6ba1bcd..9d8fb5a 100644
--- a/trace-viewer/trace_viewer/core/tracks/track.html
+++ b/trace-viewer/trace_viewer/core/tracks/track.html
@@ -16,18 +16,18 @@
  * using a child canvas element. Uses a FastRectRenderer to draw only
  * the visible slices.
  */
-tv.exportTo('tv.c.tracks', function() {
+tr.exportTo('tr.c.tracks', function() {
   /**
    * The base class for all tracks.
    * @constructor
    */
-  var Track = tv.b.ui.define('track',
-                             tv.b.ui.ContainerThatDecoratesItsChildren);
+  var Track = tr.b.ui.define('track',
+                             tr.b.ui.ContainerThatDecoratesItsChildren);
   Track.prototype = {
-    __proto__: tv.b.ui.ContainerThatDecoratesItsChildren.prototype,
+    __proto__: tr.b.ui.ContainerThatDecoratesItsChildren.prototype,
 
     decorate: function(viewport) {
-      tv.b.ui.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);
+      tr.b.ui.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);
       if (viewport === undefined)
         throw new Error('viewport is required when creating a Track.');
 
@@ -42,7 +42,7 @@
     get drawingContainer() {
       var cur = this;
       while (cur) {
-        if (cur instanceof tv.c.tracks.DrawingContainer)
+        if (cur instanceof tr.c.tracks.DrawingContainer)
           return cur;
         cur = cur.parentElement;
       }
@@ -146,7 +146,7 @@
 
     addClosestInstantEventToSelection: function(instantEvents, worldX,
                                                 worldMaxDist, selection) {
-      var instantEvent = tv.b.findClosestElementInSortedArray(
+      var instantEvent = tr.b.findClosestElementInSortedArray(
           instantEvents,
           function(x) { return x.start; },
           worldX,
diff --git a/trace-viewer/trace_viewer/core/tracks/x_marker_annotation_view.html b/trace-viewer/trace_viewer/core/tracks/x_marker_annotation_view.html
index 74e354b..0ff2dda 100644
--- a/trace-viewer/trace_viewer/core/tracks/x_marker_annotation_view.html
+++ b/trace-viewer/trace_viewer/core/tracks/x_marker_annotation_view.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.annotations', function() {
+tr.exportTo('tr.c.annotations', function() {
   /**
    * A view that draws a vertical line on the timeline at a specific timestamp.
    * @extends {AnnotationView}
@@ -22,14 +22,14 @@
   }
 
   XMarkerAnnotationView.prototype = {
-    __proto__: tv.c.annotations.AnnotationView.prototype,
+    __proto__: tr.c.annotations.AnnotationView.prototype,
 
     draw: function(ctx) {
       var dt = this.viewport_.currentDisplayTransform;
       var viewX = dt.xWorldToView(this.annotation_.timestamp);
 
       ctx.beginPath();
-      tv.c.drawLine(ctx, viewX, 0, viewX, ctx.canvas.height);
+      tr.c.drawLine(ctx, viewX, 0, viewX, ctx.canvas.height);
       ctx.strokeStyle = this.annotation_.strokeStyle;
       ctx.stroke();
     }
diff --git a/trace-viewer/trace_viewer/core/ui_state.html b/trace-viewer/trace_viewer/core/ui_state.html
index 613c2ed..9258055 100644
--- a/trace-viewer/trace_viewer/core/ui_state.html
+++ b/trace-viewer/trace_viewer/core/ui_state.html
@@ -10,8 +10,8 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
-  var Location = tv.c.Location;
+tr.exportTo('tr.c', function() {
+  var Location = tr.c.Location;
 
   /**
    * UIState is a class that represents the current state of the timeline by
@@ -47,7 +47,7 @@
     if (!viewport.containerToTrackObj.getTrackByStableId(stableId))
       throw new Error('Invalid StableID given in UI State String.');
 
-    var loc = tv.c.Location.fromStableIdAndTimestamp(
+    var loc = tr.c.Location.fromStableIdAndTimestamp(
         viewport, stableId, timestamp);
     return new UIState(loc, scaleX);
   }
diff --git a/trace-viewer/trace_viewer/core/ui_state_test.html b/trace-viewer/trace_viewer/core/ui_state_test.html
index 3c517ba..9f5f480 100644
--- a/trace-viewer/trace_viewer/core/ui_state_test.html
+++ b/trace-viewer/trace_viewer/core/ui_state_test.html
@@ -12,18 +12,18 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var UIState = tv.c.UIState;
+tr.b.unittest.testSuite(function() {
+  var UIState = tr.c.UIState;
 
   function FakeModel() {
     this.processes = { 1: { threads: { 2: { stableId: '1.2' } } } };
   }
 
-  // FakeTrack needs to be an instance of tv.c.tracks.Track because a
+  // FakeTrack needs to be an instance of tr.c.tracks.Track because a
   // location is constructed in terms of Track instances.
   function FakeTrack() { }
   FakeTrack.prototype = {
-    __proto__: tv.c.tracks.Track.prototype,
+    __proto__: tr.c.tracks.Track.prototype,
 
     get eventContainer() {
       return { stableId: '1.2' };
diff --git a/trace-viewer/trace_viewer/extras/__init__.py b/trace-viewer/trace_viewer/extras/__init__.py
new file mode 100644
index 0000000..727e987
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (c) 2012 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.
+
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/about_tracing.html b/trace-viewer/trace_viewer/extras/about_tracing/about_tracing.html
index f6b6c8a..9afeb23 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/about_tracing.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/about_tracing.html
@@ -10,11 +10,11 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   window.profilingView = undefined;  // Made global for debugging purposes only.
 
   document.addEventListener('DOMContentLoaded', function() {
-    window.profilingView = new tv.e.about_tracing.ProfilingView();
+    window.profilingView = new tr.e.about_tracing.ProfilingView();
     document.body.appendChild(profilingView);
   });
 
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/inspector_connection.html b/trace-viewer/trace_viewer/extras/about_tracing/inspector_connection.html
index df37614..ccd83c3 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/inspector_connection.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/inspector_connection.html
@@ -13,7 +13,7 @@
  * Contains connection code that inspector's embedding framework calls on
  * tracing, and that tracing can use to talk to inspector.
  */
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   // Interface used by inspector when it hands data to us from the backend.
   window.DevToolsAPI = {
     setToolbarColors: function() { },
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client.html b/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client.html
index e9b0185..f3247b6 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   function createResolvedPromise(data) {
     var promise = new Promise(function(resolve, reject) {
       if (data)
@@ -43,12 +43,12 @@
   function InspectorTracingControllerClient() {
     this.recording_ = false;
     this.bufferUsage_ = 0;
-    this.conn_ = tv.e.about_tracing.InspectorConnection.instance;
+    this.conn_ = tr.e.about_tracing.InspectorConnection.instance;
     this.currentTraceTextChunks_ = undefined;
   }
 
   InspectorTracingControllerClient.prototype = {
-    __proto__: tv.e.about_tracing.TracingControllerClient.prototype,
+    __proto__: tr.e.about_tracing.TracingControllerClient.prototype,
 
     beginMonitoring: function(monitoringOptions) {
       throw new Error('Not implemented');
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client_test.html b/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client_test.html
index d655c73..b25cce8 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client_test.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/inspector_tracing_controller_client_test.html
@@ -10,9 +10,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('beginRecording_sendCategoriesAndOptions', function() {
-    var controller = new tv.e.about_tracing.InspectorTracingControllerClient();
+    var controller = new tr.e.about_tracing.InspectorTracingControllerClient();
     controller.conn_ = new (function() {
       this.req = function(method, params) {
         var msg = JSON.stringify({
@@ -54,20 +54,20 @@
 
   test('oldFormat', function() {
     var chunks = [];
-    tv.e.about_tracing.appendTraceChunksTo(chunks, '"{ "method": "Tracing.dataCollected", "params": { "value": [ {"cat":"__metadata","pid":28871,"tid":0,"ts":0,"ph":"M","name":"num_cpus","args":{"number":4}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_sort_index","args":{"sort_index":-5}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_name","args":{"name":"Renderer"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_labels","args":{"labels":"JS Bin"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_sort_index","args":{"sort_index":-1}},{"cat":"__metadata","pid":28871,"tid":28917,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Compositor"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Chrome_ChildIOThread"}},{"cat":"__metadata","pid":28871,"tid":28919,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CompositorRasterWorker1/28919"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CrRendererMain"}},{"cat":"ipc,toplevel","pid":28871,"tid":28911,"ts":22000084746,"ph":"X","name":"ChannelReader::DispatchInputData","args":{"class":64,"line":25},"tdur":0,"tts":1853064},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"overhead","args":{"average_overhead":0.015}} ] } }"'); // @suppress longLineCheck
+    tr.e.about_tracing.appendTraceChunksTo(chunks, '"{ "method": "Tracing.dataCollected", "params": { "value": [ {"cat":"__metadata","pid":28871,"tid":0,"ts":0,"ph":"M","name":"num_cpus","args":{"number":4}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_sort_index","args":{"sort_index":-5}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_name","args":{"name":"Renderer"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_labels","args":{"labels":"JS Bin"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_sort_index","args":{"sort_index":-1}},{"cat":"__metadata","pid":28871,"tid":28917,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Compositor"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Chrome_ChildIOThread"}},{"cat":"__metadata","pid":28871,"tid":28919,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CompositorRasterWorker1/28919"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CrRendererMain"}},{"cat":"ipc,toplevel","pid":28871,"tid":28911,"ts":22000084746,"ph":"X","name":"ChannelReader::DispatchInputData","args":{"class":64,"line":25},"tdur":0,"tts":1853064},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"overhead","args":{"average_overhead":0.015}} ] } }"'); // @suppress longLineCheck
     assert.equal(chunks.length, 1);
     JSON.parse('[' + chunks.join('') + ']');
   });
 
   test('newFormat', function() {
     var chunks = [];
-    tv.e.about_tracing.appendTraceChunksTo(chunks, '"{ "method": "Tracing.dataCollected", "params": { "value": [{"cat":"__metadata","pid":28871,"tid":0,"ts":0,"ph":"M","name":"num_cpus","args":{"number":4}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_sort_index","args":{"sort_index":-5}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_name","args":{"name":"Renderer"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_labels","args":{"labels":"JS Bin"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_sort_index","args":{"sort_index":-1}},{"cat":"__metadata","pid":28871,"tid":28917,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Compositor"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Chrome_ChildIOThread"}},{"cat":"__metadata","pid":28871,"tid":28919,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CompositorRasterWorker1/28919"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CrRendererMain"}},{"cat":"ipc,toplevel","pid":28871,"tid":28911,"ts":22000084746,"ph":"X","name":"ChannelReader::DispatchInputData","args":{"class":64,"line":25},"tdur":0,"tts":1853064},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"overhead","args":{"average_overhead":0.015}}] } }"'); // @suppress longLineCheck
+    tr.e.about_tracing.appendTraceChunksTo(chunks, '"{ "method": "Tracing.dataCollected", "params": { "value": [{"cat":"__metadata","pid":28871,"tid":0,"ts":0,"ph":"M","name":"num_cpus","args":{"number":4}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_sort_index","args":{"sort_index":-5}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_name","args":{"name":"Renderer"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_labels","args":{"labels":"JS Bin"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_sort_index","args":{"sort_index":-1}},{"cat":"__metadata","pid":28871,"tid":28917,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Compositor"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Chrome_ChildIOThread"}},{"cat":"__metadata","pid":28871,"tid":28919,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CompositorRasterWorker1/28919"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CrRendererMain"}},{"cat":"ipc,toplevel","pid":28871,"tid":28911,"ts":22000084746,"ph":"X","name":"ChannelReader::DispatchInputData","args":{"class":64,"line":25},"tdur":0,"tts":1853064},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"overhead","args":{"average_overhead":0.015}}] } }"'); // @suppress longLineCheck
     assert.equal(chunks.length, 1);
     JSON.parse('[' + chunks.join('') + ']');
   });
 
   test('stringAndObjectPayload', function() {
-    var connection = new tv.e.about_tracing.InspectorConnection();
+    var connection = new tr.e.about_tracing.InspectorConnection();
     connection.setNotificationListener('Tracing.dataCollected',
         function(message) {
           assert.typeOf(message, 'string');
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/mock_tracing_controller_client.html b/trace-viewer/trace_viewer/extras/about_tracing/mock_tracing_controller_client.html
index fdde15c..2354f50 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/mock_tracing_controller_client.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/mock_tracing_controller_client.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   function MockTracingControllerClient() {
     this.requests = [];
     this.nextRequestIndex = 0;
@@ -18,7 +18,7 @@
   }
 
   MockTracingControllerClient.prototype = {
-    __proto__: tv.e.about_tracing.TracingControllerClient.prototype,
+    __proto__: tr.e.about_tracing.TracingControllerClient.prototype,
 
     expectRequest: function(method, generateResponse) {
       var generateResponseCb;
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/profiling_view.html b/trace-viewer/trace_viewer/extras/about_tracing/profiling_view.html
index 55a9151..4856fcc 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/profiling_view.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/profiling_view.html
@@ -45,7 +45,7 @@
 </style>
 
 <template id="profiling-view-template">
-  <tv-b-ui-info-bar-group></tv-b-ui-info-bar-group>
+  <tr-b-ui-info-bar-group></tr-b-ui-info-bar-group>
   <x-timeline-view>
     <x-timeline-view-buttons>
       <button id="record-button">Record</button>
@@ -68,7 +68,7 @@
  * @fileoverview ProfilingView glues the View control to
  * TracingController.
  */
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   function readFile(file) {
     return new Promise(function(resolve, reject) {
       var reader = new FileReader();
@@ -93,7 +93,7 @@
    * @constructor
    * @extends {HTMLUnknownElement}
    */
-  var ProfilingView = tv.b.ui.define('x-profiling-view');
+  var ProfilingView = tr.b.ui.define('x-profiling-view');
   var THIS_DOC = document.currentScript.ownerDocument;
   var REPORT_UPLOAD_URL = 'http://crash-staging/';
 
@@ -101,13 +101,13 @@
     __proto__: HTMLUnknownElement.prototype,
 
     decorate: function(tracingControllerClient) {
-      this.appendChild(tv.b.instantiateTemplate('#profiling-view-template',
+      this.appendChild(tr.b.instantiateTemplate('#profiling-view-template',
           THIS_DOC));
 
       this.timelineView_ = this.querySelector('x-timeline-view');
-      tv.b.ui.decorate(this.timelineView_, tv.c.TimelineView);
+      tr.b.ui.decorate(this.timelineView_, tr.c.TimelineView);
 
-      this.infoBarGroup_ = this.querySelector('tv-b-ui-info-bar-group');
+      this.infoBarGroup_ = this.querySelector('tr-b-ui-info-bar-group');
 
       // Detach the buttons. We will reattach them to the timeline view.
       // TODO(nduca): Make timeline-view have a content select="x-buttons"
@@ -117,7 +117,7 @@
       this.timelineView_.leftControls.appendChild(buttons);
       this.initButtons_(buttons);
 
-      tv.b.KeyEventManager.instance.addListener(
+      tr.b.KeyEventManager.instance.addListener(
           'keypress', this.onKeypress_, this);
 
       this.initDragAndDrop_();
@@ -126,10 +126,10 @@
         this.tracingControllerClient_ = tracingControllerClient;
       } else if (window.DevToolsHost !== undefined) {
         this.tracingControllerClient_ =
-            new tv.e.about_tracing.InspectorTracingControllerClient();
+            new tr.e.about_tracing.InspectorTracingControllerClient();
       } else {
         this.tracingControllerClient_ =
-            new tv.e.about_tracing.XhrBasedTracingControllerClient();
+            new tr.e.about_tracing.XhrBasedTracingControllerClient();
       }
 
       this.isRecording_ = false;
@@ -188,7 +188,7 @@
 
     updateTracingControllerSpecificState_: function() {
       var isInspector = this.tracingControllerClient_ instanceof
-          tv.e.about_tracing.InspectorTracingControllerClient;
+          tr.e.about_tracing.InspectorTracingControllerClient;
 
       if (isInspector) {
         this.infoBarGroup_.addMessage(
@@ -212,7 +212,7 @@
       var buttons = this.querySelector('x-timeline-view-buttons');
       buttons.querySelector('#monitor-checkbox').disabled = true;
       buttons.querySelector('#monitor-checkbox').checked = false;
-      var resultPromise = tv.e.about_tracing.beginRecording(
+      var resultPromise = tr.e.about_tracing.beginRecording(
           this.tracingControllerClient_);
       resultPromise.then(
           function(data) {
@@ -223,9 +223,9 @@
           function(err) {
             this.isRecording_ = false;
             buttons.querySelector('#monitor-checkbox').disabled = false;
-            if (err instanceof tv.e.about_tracing.UserCancelledError)
+            if (err instanceof tr.e.about_tracing.UserCancelledError)
               return;
-            tv.b.ui.Overlay.showError('Error while recording', err);
+            tr.b.ui.Overlay.showError('Error while recording', err);
           }.bind(this));
       return resultPromise;
     },
@@ -237,14 +237,14 @@
         throw new Error('Already monitoring');
       var buttons = this.querySelector('x-timeline-view-buttons');
       var resultPromise =
-          tv.e.about_tracing.beginMonitoring(this.tracingControllerClient_);
+          tr.e.about_tracing.beginMonitoring(this.tracingControllerClient_);
       resultPromise.then(
           function() {
           }.bind(this),
           function(err) {
-            if (err instanceof tv.e.about_tracing.UserCancelledError)
+            if (err instanceof tr.e.about_tracing.UserCancelledError)
               return;
-            tv.b.ui.Overlay.showError('Error while monitoring', err);
+            tr.b.ui.Overlay.showError('Error while monitoring', err);
           }.bind(this));
       return resultPromise;
     },
@@ -256,14 +256,14 @@
         throw new Error('Monitoring is disabled');
       var buttons = this.querySelector('x-timeline-view-buttons');
       var resultPromise =
-          tv.e.about_tracing.endMonitoring(this.tracingControllerClient_);
+          tr.e.about_tracing.endMonitoring(this.tracingControllerClient_);
       resultPromise.then(
           function() {
           }.bind(this),
           function(err) {
-            if (err instanceof tv.e.about_tracing.UserCancelledError)
+            if (err instanceof tr.e.about_tracing.UserCancelledError)
               return;
-            tv.b.ui.Overlay.showError('Error while monitoring', err);
+            tr.b.ui.Overlay.showError('Error while monitoring', err);
           }.bind(this));
       return resultPromise;
     },
@@ -272,30 +272,30 @@
       if (!this.isMonitoring_)
         throw new Error('Monitoring is disabled');
       var resultPromise =
-          tv.e.about_tracing.captureMonitoring(this.tracingControllerClient_);
+          tr.e.about_tracing.captureMonitoring(this.tracingControllerClient_);
       resultPromise.then(
           function(data) {
             this.setActiveTrace('trace.json', data, true);
           }.bind(this),
           function(err) {
-            if (err instanceof tv.e.about_tracing.UserCancelledError)
+            if (err instanceof tr.e.about_tracing.UserCancelledError)
               return;
-            tv.b.ui.Overlay.showError('Error while monitoring', err);
+            tr.b.ui.Overlay.showError('Error while monitoring', err);
           }.bind(this));
       return resultPromise;
     },
 
     getMonitoringStatus: function() {
       var resultPromise =
-          tv.e.about_tracing.getMonitoringStatus(this.tracingControllerClient_);
+          tr.e.about_tracing.getMonitoringStatus(this.tracingControllerClient_);
       resultPromise.then(
           function(status) {
             this.onMonitoringStateChanged_(status.isMonitoring);
           }.bind(this),
           function(err) {
-            if (err instanceof tv.e.about_tracing.UserCancelledError)
+            if (err instanceof tr.e.about_tracing.UserCancelledError)
               return;
-            tv.b.ui.Overlay.showError('Error while updating tracing states',
+            tr.b.ui.Overlay.showError('Error while updating tracing states',
                                       err);
           }.bind(this));
       return resultPromise;
@@ -346,7 +346,7 @@
       this.uploadButton_.disabled = false;
       this.timelineView_.viewTitle = filename;
 
-      var m = new tv.c.TraceModel();
+      var m = new tr.Model();
       var p = m.importTracesWithProgressDialog([data], true);
       p.then(
           function() {
@@ -354,7 +354,7 @@
             this.timelineView_.updateDocumentFavicon();
           }.bind(this),
           function(err) {
-            tv.b.ui.Overlay.showError('While importing: ', err);
+            tr.b.ui.Overlay.showError('While importing: ', err);
           }.bind(this));
     },
 
@@ -457,7 +457,7 @@
     },
 
     initUploadStatusOverlay_: function() {
-      this.uploadOverlay_ = tv.b.ui.Overlay();
+      this.uploadOverlay_ = tr.b.ui.Overlay();
       this.uploadOverlay_.title = 'Uploading trace...';
       this.uploadOverlay_.userCanClose = false;
       this.uploadOverlay_.visible = true;
@@ -532,7 +532,7 @@
                   this.setActiveTrace(file.name, data);
                 }.bind(this),
                 function(err) {
-                  tv.b.ui.Overlay.showError('Error while loading file: ' + err);
+                  tr.b.ui.Overlay.showError('Error while loading file: ' + err);
                 });
           }.bind(this), false);
       inputElement.click();
@@ -574,7 +574,7 @@
 
       var files = e.dataTransfer.files;
       if (files.length !== 1) {
-        tv.b.ui.Overlay.showError('1 file supported at a time.');
+        tr.b.ui.Overlay.showError('1 file supported at a time.');
         return;
       }
 
@@ -583,7 +583,7 @@
             this.setActiveTrace(files[0].name, data);
           }.bind(this),
           function(err) {
-            tv.b.ui.Overlay.showError('Error while loading file: ' + err);
+            tr.b.ui.Overlay.showError('Error while loading file: ' + err);
           });
       return false;
     }
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/profiling_view_test.html b/trace-viewer/trace_viewer/extras/about_tracing/profiling_view_test.html
index 32b40ee..d494a96 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/profiling_view_test.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/profiling_view_test.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var testData = [
     {name: 'a', args: {}, pid: 52, ts: 15000, cat: 'foo', tid: 53, ph: 'B'},
     {name: 'a', args: {}, pid: 52, ts: 19000, cat: 'foo', tid: 53, ph: 'E'},
@@ -28,10 +28,10 @@
     useSampling: false
   };
 
-  var ProfilingView = tv.e.about_tracing.ProfilingView;
+  var ProfilingView = tr.e.about_tracing.ProfilingView;
 
   test('recording', function() {
-    var mock = new tv.e.about_tracing.MockTracingControllerClient();
+    var mock = new tr.e.about_tracing.MockTracingControllerClient();
     mock.allowLooping = true;
     mock.expectRequest('getMonitoringStatus', function() {
       return btoa(JSON.stringify(monitoringOptions));
@@ -75,7 +75,7 @@
   });
 
   test('monitoring', function() {
-    var mock = new tv.e.about_tracing.MockTracingControllerClient();
+    var mock = new tr.e.about_tracing.MockTracingControllerClient();
     mock.allowLooping = true;
     mock.expectRequest('getMonitoringStatus', function() {
       return btoa(JSON.stringify(monitoringOptions));
@@ -129,7 +129,7 @@
   });
 
   test('upload', function() {
-    var mock = new tv.e.about_tracing.MockTracingControllerClient();
+    var mock = new tr.e.about_tracing.MockTracingControllerClient();
     mock.allowLooping = true;
     mock.expectRequest('getMonitoringStatus', function() {
       return btoa(JSON.stringify(monitoringOptions));
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller.html b/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller.html
index ba6f0d0..f56d4ee 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   function beginMonitoring(tracingControllerClient) {
     var finalPromiseResolver;
     var finalPromise = new Promise(function(resolve, reject) {
@@ -65,8 +65,6 @@
   }
 
   function beginRecording(tracingControllerClient) {
-    var defaultTitle = document.title;
-    var toggleRecordingIndicator = false;
     var finalPromiseResolver;
     var finalPromise = new Promise(function(resolve, reject) {
       finalPromiseResolver = {
@@ -103,9 +101,9 @@
     // Step 2: Show tracing dialog.
     var selectionDlg;
     function showTracingDialog(categories) {
-      selectionDlg = new tv.e.about_tracing.RecordSelectionDialog();
+      selectionDlg = new tr.e.about_tracing.RecordSelectionDialog();
       selectionDlg.categories = categories;
-      selectionDlg.settings_key = 'tv.e.about_tracing.record_selection_dialog';
+      selectionDlg.settings_key = 'tr.e.about_tracing.record_selection_dialog';
       selectionDlg.addEventListener('recordclick', startTracing);
       selectionDlg.addEventListener('closeclick', cancelRecording);
       selectionDlg.visible = true;
@@ -122,7 +120,7 @@
     var progressDlg;
     var bufferPercentFullDiv;
     function startTracing() {
-      progressDlg = new tv.b.ui.Overlay();
+      progressDlg = new tr.b.ui.Overlay();
       progressDlg.textContent = 'Recording...';
       progressDlg.userCanClose = false;
 
@@ -168,7 +166,6 @@
             recordFailed);
         stopButton.disabled = true;
         bufferPercentFullDiv = undefined;
-        document.title = defaultTitle;
       });
       finalPromise.progressDlg = progressDlg;
     }
@@ -202,14 +199,6 @@
       if (bufferPercentFullDiv.textContent != newText)
         bufferPercentFullDiv.textContent = newText;
 
-      document.title = 'tracing: ' + percent_full + '%';
-      if (toggleRecordingIndicator)
-        document.title = document.title + ' \u25AA';
-      if (percent_full < 100)
-          toggleRecordingIndicator = !toggleRecordingIndicator;
-      else
-          toggleRecordingIndicator = false;
-
       window.setTimeout(getBufferPercentFull, 500);
     }
 
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller_test.html b/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller_test.html
index 3449230..e68af83 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller_test.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/record_and_capture_controller_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   var testData = [
     {name: 'a', args: {}, pid: 52, ts: 15000, cat: 'foo', tid: 53, ph: 'B'},
     {name: 'a', args: {}, pid: 52, ts: 19000, cat: 'foo', tid: 53, ph: 'E'},
@@ -21,7 +21,7 @@
 
   test('fullRecording', function() {
     return new Promise(function(resolve, reject) {
-      var mock = new tv.e.about_tracing.MockTracingControllerClient();
+      var mock = new tr.e.about_tracing.MockTracingControllerClient();
       mock.expectRequest('endRecording', function() {
         return '';
       });
@@ -45,7 +45,7 @@
         return JSON.stringify(testData);
       });
 
-      var recordingPromise = tv.e.about_tracing.beginRecording(mock);
+      var recordingPromise = tr.e.about_tracing.beginRecording(mock);
 
       return recordingPromise.then(
           function(data) {
@@ -62,7 +62,7 @@
 
   test('monitoring', function() {
     return new Promise(function(resolve, reject) {
-      var mock = new tv.e.about_tracing.MockTracingControllerClient();
+      var mock = new tr.e.about_tracing.MockTracingControllerClient();
 
       mock.expectRequest('beginMonitoring', function(monitoringOptions) {
         assert.typeOf(monitoringOptions.categoryFilter, 'string');
@@ -70,7 +70,7 @@
         assert.typeOf(monitoringOptions.useSampling, 'boolean');
         assert.typeOf(monitoringOptions.tracingRecordMode, 'string');
         setTimeout(function() {
-          var capturePromise = tv.e.about_tracing.captureMonitoring(mock);
+          var capturePromise = tr.e.about_tracing.captureMonitoring(mock);
           capturePromise.then(
               function(data) {
                 var testDataString = JSON.stringify(testData);
@@ -85,7 +85,7 @@
 
       mock.expectRequest('captureMonitoring', function(data) {
         setTimeout(function() {
-          var endPromise = tv.e.about_tracing.endMonitoring(mock);
+          var endPromise = tr.e.about_tracing.endMonitoring(mock);
           endPromise.then(
               function(data) {
                 mock.assertAllRequestsHandled();
@@ -101,8 +101,8 @@
       mock.expectRequest('endMonitoring', function(data) {
       });
 
-      tv.e.about_tracing.beginMonitoring(mock);
+      tr.e.about_tracing.beginMonitoring(mock);
     });
   });
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog.html b/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog.html
index 9ca6bbc..96c7d45 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog.html
@@ -8,7 +8,7 @@
 <link rel="import" href="/base/utils.html">
 <link rel="import" href="/base/ui/overlay.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
-<link rel="import" href="/base/ui/info_bar.html">
+<link rel="import" href="/base/ui/info_bar_group.html">
 
 <template id="record-selection-dialog-template">
   <style>
@@ -114,7 +114,7 @@
   </style>
 
   <div class="record-selection-dialog">
-    <tv-b-ui-info-bar-group></tv-b-ui-info-bar-group>
+    <tr-b-ui-info-bar-group></tr-b-ui-info-bar-group>
     <div class="category-presets">
     </div>
     <div class="category-description"></div>
@@ -151,11 +151,11 @@
 
 /**
  * @fileoverview RecordSelectionDialog presents the available categories
- * to be enabled/disabled during tv.c.
+ * to be enabled/disabled during tr.c.
  */
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
-  var RecordSelectionDialog = tv.b.ui.define('div');
+  var RecordSelectionDialog = tr.b.ui.define('div');
 
   var DEFAULT_PRESETS = [
     {title: 'Web developer',
@@ -190,15 +190,15 @@
   var DEFAULT_SAMPLING_TRACING = false;
 
   RecordSelectionDialog.prototype = {
-    __proto__: tv.b.ui.Overlay.prototype,
+    __proto__: tr.b.ui.Overlay.prototype,
 
     decorate: function() {
-      tv.b.ui.Overlay.prototype.decorate.call(this);
+      tr.b.ui.Overlay.prototype.decorate.call(this);
       this.title = 'Record a new trace...';
 
       this.classList.add('record-dialog-overlay');
 
-      var node = tv.b.instantiateTemplate('#record-selection-dialog-template',
+      var node = tr.b.instantiateTemplate('#record-selection-dialog-template',
           THIS_DOC);
       this.appendChild(node);
 
@@ -212,7 +212,7 @@
 
       this.categoriesView_ = this.querySelector('.categories-column-view');
       this.presetsEl_ = this.querySelector('.category-presets');
-      this.presetsEl_.appendChild(tv.b.ui.createOptionGroup(
+      this.presetsEl_.appendChild(tr.b.ui.createOptionGroup(
           this, 'currentlyChosenPreset',
           'about_tracing.record_selection_dialog_preset',
           DEFAULT_PRESETS[0].categoryFilter,
@@ -220,16 +220,16 @@
             return { label: p.title, value: p.categoryFilter };
           })));
 
-      this.tracingRecordModeSltr_ = tv.b.ui.createSelector(
+      this.tracingRecordModeSltr_ = tr.b.ui.createSelector(
           this, 'tracingRecordMode',
           'recordSelectionDialog.tracingRecordMode',
           DEFAULT_RECORD_MODE, RECORDING_MODES);
 
-      this.systemTracingBn_ = tv.b.ui.createCheckBox(
+      this.systemTracingBn_ = tr.b.ui.createCheckBox(
           undefined, undefined,
           'recordSelectionDialog.useSystemTracing', true,
           'System tracing');
-      this.samplingTracingBn_ = tv.b.ui.createCheckBox(
+      this.samplingTracingBn_ = tr.b.ui.createCheckBox(
           undefined, undefined,
           'recordSelectionDialog.useSampling', false,
           'State sampling');
@@ -253,10 +253,10 @@
           this.querySelector('.warning-default-disabled-categories'));
       this.editCategoriesOpened_ = false;
 
-      // TODO(chrishenry): When used with tv.b.ui.Overlay (such as in
+      // TODO(chrishenry): When used with tr.b.ui.Overlay (such as in
       // chrome://tracing, this does not yet look quite right due to
       // the 10px overlay content padding (but it's good enough).
-      this.infoBarGroup_ = this.querySelector('tv-b-ui-info-bar-group');
+      this.infoBarGroup_ = this.querySelector('tr-b-ui-info-bar-group');
 
       this.addEventListener('visibleChange', this.onVisibleChange_.bind(this));
     },
@@ -362,7 +362,7 @@
         for (var j = 0; j < categoryGroup.length; ++j) {
           var categoryEl = categoryGroup[j].children[0];
           categoryEl.checked = shouldReadFromSettings ?
-              tv.b.Settings.get(categoryEl.value, false, this.settings_key_) :
+              tr.b.Settings.get(categoryEl.value, false, this.settings_key_) :
               false;
         }
       }
@@ -377,6 +377,8 @@
         for (var i = 0; i < this.currentlyChosenPreset_.length; ++i) {
           var categoryEl = document.getElementById(
               this.currentlyChosenPreset_[i]);
+          if (!categoryEl)
+            continue;
           categoryEl.checked = true;
         }
       }
@@ -457,7 +459,7 @@
 
     onRecordButtonClicked_: function() {
       this.visible = false;
-      tv.b.dispatchSimpleEvent(this, 'recordclick');
+      tr.b.dispatchSimpleEvent(this, 'recordclick');
       return false;
     },
 
@@ -499,7 +501,7 @@
         inputEl.id = category;
         inputEl.value = category;
 
-        inputEl.checked = tv.b.Settings.get(
+        inputEl.checked = tr.b.Settings.get(
             category, checkedDefault, this.settings_key_);
         inputEl.onclick = this.updateSetting_.bind(this);
 
@@ -520,7 +522,7 @@
       // returned when we query the category list.
       var categorySet = {};
       var allCategories =
-          this.categories_.concat(tv.b.Settings.keys(this.settings_key_));
+          this.categories_.concat(tr.b.Settings.keys(this.settings_key_));
       var allCategoriesLength = allCategories.length;
       for (var i = 0; i < allCategoriesLength; ++i)
         categorySet[allCategories[i]] = true;
@@ -561,7 +563,7 @@
 
     updateSetting_: function(e) {
       var checkbox = e.target;
-      tv.b.Settings.set(checkbox.value, checkbox.checked, this.settings_key_);
+      tr.b.Settings.set(checkbox.value, checkbox.checked, this.settings_key_);
 
       // Change the current record mode to 'Manually select settings' from
       // preset mode if and only if currently user is in preset record mode
@@ -621,7 +623,7 @@
 
     createDefaultDisabledWarningDialog_: function(warningLink) {
       function onClickHandler(evt) {
-        this.warningOverlay_ = tv.b.ui.Overlay();
+        this.warningOverlay_ = tr.b.ui.Overlay();
         this.warningOverlay_.parentEl_ = this;
         this.warningOverlay_.title = 'Warning...';
         this.warningOverlay_.userCanClose = true;
@@ -629,7 +631,7 @@
 
         this.setWarningDialogOverlayText_([
           'Enabling the default disabled categories may have',
-          'performance and memory impact while tv.c.'
+          'performance and memory impact while tr.c.'
         ]);
 
         evt.preventDefault();
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog_test.html b/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog_test.html
index 89c92d9..f204b3c 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog_test.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/record_selection_dialog_test.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('instantitate', function() {
     var categories = [];
     for (var i = 0; i < 30; i++)
@@ -23,7 +23,7 @@
     categories.push('first,second,third');
     categories.push('cc,disabled-by-default-cc.debug');
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = categories;
     dlg.settings_key = 'key';
     dlg.currentlyChosenPreset = [];
@@ -38,7 +38,7 @@
   });
 
   test('recordSelectionDialog_splitCategories', function() {
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories =
         ['cc,disabled-by-default-one,cc.debug', 'two,three', 'three'];
     dlg.settings_key = 'key';
@@ -59,7 +59,7 @@
   });
 
   test('recordSelectionDialog_UpdateForm_NoSettings', function() {
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-one', 'two', 'three'];
     dlg.settings_key = 'key';
     dlg.currentlyChosenPreset = [];
@@ -87,10 +87,10 @@
   });
 
   test('recordSelectionDialog_UpdateForm_Settings', function() {
-    tv.b.Settings.set('two', true, 'categories');
-    tv.b.Settings.set('three', false, 'categories');
+    tr.b.Settings.set('two', true, 'categories');
+    tr.b.Settings.set('three', false, 'categories');
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-one'];
     dlg.settings_key = 'categories';
     dlg.currentlyChosenPreset = [];
@@ -118,7 +118,7 @@
   });
 
   test('recordSelectionDialog_UpdateForm_DisabledByDefault', function() {
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-bar', 'baz'];
     dlg.settings_key = 'categories';
     dlg.currentlyChosenPreset = [];
@@ -132,14 +132,14 @@
     assert.equal(dlg.categoryFilter(), 'disabled-by-default-bar');
 
     assert.isFalse(
-        tv.b.Settings.get('disabled-by-default-foo', false, 'categories'));
+        tr.b.Settings.get('disabled-by-default-foo', false, 'categories'));
   });
 
   test('selectAll', function() {
-    tv.b.Settings.set('two', true, 'categories');
-    tv.b.Settings.set('three', false, 'categories');
+    tr.b.Settings.set('two', true, 'categories');
+    tr.b.Settings.set('three', false, 'categories');
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-one'];
     dlg.settings_key = 'categories';
     dlg.currentlyChosenPreset = [];
@@ -147,10 +147,10 @@
   });
 
   test('selectNone', function() {
-    tv.b.Settings.set('two', true, 'categories');
-    tv.b.Settings.set('three', false, 'categories');
+    tr.b.Settings.set('two', true, 'categories');
+    tr.b.Settings.set('three', false, 'categories');
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-one'];
     dlg.settings_key = 'categories';
     dlg.currentlyChosenPreset = [];
@@ -159,13 +159,13 @@
     // Enables the three option, two already enabled.
     dlg.querySelector('.default-enabled-categories .all-btn').click();
     assert.equal(dlg.categoryFilter(), '');
-    assert.isTrue(tv.b.Settings.get('three', false, 'categories'));
+    assert.isTrue(tr.b.Settings.get('three', false, 'categories'));
 
     // Disables three and two.
     dlg.querySelector('.default-enabled-categories .none-btn').click();
     assert.equal(dlg.categoryFilter(), '-three,-two');
-    assert.isFalse(tv.b.Settings.get('two', false, 'categories'));
-    assert.isFalse(tv.b.Settings.get('three', false, 'categories'));
+    assert.isFalse(tr.b.Settings.get('two', false, 'categories'));
+    assert.isFalse(tr.b.Settings.get('three', false, 'categories'));
 
     // Turn categories back on so they can be ignored.
     dlg.querySelector('.default-enabled-categories .all-btn').click();
@@ -174,26 +174,26 @@
     dlg.querySelector('.default-disabled-categories .all-btn').click();
     assert.equal(dlg.categoryFilter(), 'disabled-by-default-one');
     assert.isTrue(
-        tv.b.Settings.get('disabled-by-default-one', false, 'categories'));
+        tr.b.Settings.get('disabled-by-default-one', false, 'categories'));
 
     // Turn disabled by default back off.
     dlg.querySelector('.default-disabled-categories .none-btn').click();
     assert.equal(dlg.categoryFilter(), '');
     assert.isFalse(
-        tv.b.Settings.get('disabled-by-default-one', false, 'categories'));
+        tr.b.Settings.get('disabled-by-default-one', false, 'categories'));
   });
 
   test('recordSelectionDialog_noPreset', function() {
-    tv.b.Settings.set('about_tracing.record_selection_dialog_preset', []);
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    tr.b.Settings.set('about_tracing.record_selection_dialog_preset', []);
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     assert.isFalse(dlg.usingPreset_());
   });
 
   test('recordSelectionDialog_defaultPreset', function() {
-    tv.b.Settings.set('two', true, 'categories');
-    tv.b.Settings.set('three', false, 'categories');
+    tr.b.Settings.set('two', true, 'categories');
+    tr.b.Settings.set('three', false, 'categories');
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-one'];
     dlg.settings_key = 'categories';
     // Note: currentlyChosenPreset is not set here, so the default is used.
@@ -226,15 +226,15 @@
   });
 
   test('recordSelectionDialog_changePresets', function() {
-    tv.b.Settings.set('two', true, 'categories');
-    tv.b.Settings.set('three', false, 'categories');
-    tv.b.Settings.set('disabled-by-default-cc.debug', true, 'categories');
-    tv.b.Settings.set('recordSelectionDialog.tracingRecordMode',
+    tr.b.Settings.set('two', true, 'categories');
+    tr.b.Settings.set('three', false, 'categories');
+    tr.b.Settings.set('disabled-by-default-cc.debug', true, 'categories');
+    tr.b.Settings.set('recordSelectionDialog.tracingRecordMode',
         'record-as-much-as-possible');
-    tv.b.Settings.set('recordSelectionDialog.useSystemTracing', true);
-    tv.b.Settings.set('recordSelectionDialog.useSampling', false);
+    tr.b.Settings.set('recordSelectionDialog.useSystemTracing', true);
+    tr.b.Settings.set('recordSelectionDialog.useSampling', false);
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-one'];
     dlg.settings_key = 'categories';
     // Note: currentlyChosenPreset is not set here, so the default is used.
@@ -279,16 +279,16 @@
   });
 
   test('recordSelectionDialog_savedPreset', function() {
-    tv.b.Settings.set('two', true, 'categories');
-    tv.b.Settings.set('three', false, 'categories');
-    tv.b.Settings.set('recordSelectionDialog.tracingRecordMode',
+    tr.b.Settings.set('two', true, 'categories');
+    tr.b.Settings.set('three', false, 'categories');
+    tr.b.Settings.set('recordSelectionDialog.tracingRecordMode',
         'record-continuously');
-    tv.b.Settings.set('recordSelectionDialog.useSystemTracing', true);
-    tv.b.Settings.set('recordSelectionDialog.useSampling', true);
-    tv.b.Settings.set('tv.e.about_tracing.record_selection_dialog_preset',
+    tr.b.Settings.set('recordSelectionDialog.useSystemTracing', true);
+    tr.b.Settings.set('recordSelectionDialog.useSampling', true);
+    tr.b.Settings.set('tr.e.about_tracing.record_selection_dialog_preset',
         ['blink', 'cc', 'renderer', 'cc.debug']);
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.categories = ['disabled-by-default-one'];
     dlg.settings_key = 'categories';
     dlg.updateForm_();
@@ -315,15 +315,15 @@
   });
 
   test('recordSelectionDialog_categoryFilters', function() {
-    tv.b.Settings.set('default1', true, 'categories');
-    tv.b.Settings.set('disabled1', false, 'categories');
-    tv.b.Settings.set('disabled-by-default-cc.disabled2', false, 'categories');
-    tv.b.Settings.set('input', true, 'categories');
-    tv.b.Settings.set('blink', true, 'categories');
-    tv.b.Settings.set('cc', false, 'categories');
-    tv.b.Settings.set('disabled-by-default-cc.debug', true, 'categories');
+    tr.b.Settings.set('default1', true, 'categories');
+    tr.b.Settings.set('disabled1', false, 'categories');
+    tr.b.Settings.set('disabled-by-default-cc.disabled2', false, 'categories');
+    tr.b.Settings.set('input', true, 'categories');
+    tr.b.Settings.set('blink', true, 'categories');
+    tr.b.Settings.set('cc', false, 'categories');
+    tr.b.Settings.set('disabled-by-default-cc.debug', true, 'categories');
 
-    var dlg = new tv.e.about_tracing.RecordSelectionDialog();
+    var dlg = new tr.e.about_tracing.RecordSelectionDialog();
     dlg.settings_key = 'categories';
     dlg.categories = [];
     dlg.currentlyChosenPreset = [];
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/tracing_controller_client.html b/trace-viewer/trace_viewer/extras/about_tracing/tracing_controller_client.html
index 8114e59..a05b690 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/tracing_controller_client.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/tracing_controller_client.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   /**
    * Communicates with content/browser/tracing_controller_impl.cc
    *
diff --git a/trace-viewer/trace_viewer/extras/about_tracing/xhr_based_tracing_controller_client.html b/trace-viewer/trace_viewer/extras/about_tracing/xhr_based_tracing_controller_client.html
index 12beaa6..40b3d94 100644
--- a/trace-viewer/trace_viewer/extras/about_tracing/xhr_based_tracing_controller_client.html
+++ b/trace-viewer/trace_viewer/extras/about_tracing/xhr_based_tracing_controller_client.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.about_tracing', function() {
+tr.exportTo('tr.e.about_tracing', function() {
   function beginXhr(method, path, data) {
     if (data === undefined)
       data = null;
@@ -40,7 +40,7 @@
   function XhrBasedTracingControllerClient() { }
 
   XhrBasedTracingControllerClient.prototype = {
-    __proto__: tv.e.about_tracing.TracingControllerClient.prototype,
+    __proto__: tr.e.about_tracing.TracingControllerClient.prototype,
 
     beginMonitoring: function(monitoringOptions) {
       var monitoringOptionsB64 = btoa(JSON.stringify(monitoringOptions));
diff --git a/trace-viewer/trace_viewer/extras/analysis/sampling_summary.html b/trace-viewer/trace_viewer/extras/analysis/sampling_summary.html
index aa8e08d..673ec72 100644
--- a/trace-viewer/trace_viewer/extras/analysis/sampling_summary.html
+++ b/trace-viewer/trace_viewer/extras/analysis/sampling_summary.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/base/iteration_helpers.html">
 <link rel="import" href="/base/statistics.html">
@@ -129,11 +129,11 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.analysis', function() {
+tr.exportTo('tr.e.analysis', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
-  var RequestSelectionChangeEvent = tv.c.RequestSelectionChangeEvent;
-  var getColorOfKey = tv.b.ui.getColorOfKey;
+  var RequestSelectionChangeEvent = tr.c.RequestSelectionChangeEvent;
+  var getColorOfKey = tr.b.ui.getColorOfKey;
 
   /**
     * @constructor
@@ -302,7 +302,7 @@
    * @constructor
    */
   var SamplingSummaryPanel =
-      tv.b.ui.define('x-sample-summary-panel');
+      tr.b.ui.define('x-sample-summary-panel');
   SamplingSummaryPanel.textLabel = 'Sampling Summary';
   SamplingSummaryPanel.supportsModel = function(m) {
     if (m == undefined) {
@@ -333,7 +333,7 @@
       var sample = selection[i];
       var id = sample.leafStackFrame.id;
       if (!stackFrameIdToSamples[id])
-        stackFrameIdToSamples[id] = new tv.c.Selection();
+        stackFrameIdToSamples[id] = new tr.c.Selection();
       stackFrameIdToSamples[id].push(sample);
     }
     return stackFrameIdToSamples;
@@ -344,7 +344,7 @@
 
     decorate: function() {
       this.classList.add('x-sample-summary-panel');
-      this.appendChild(tv.b.instantiateTemplate(
+      this.appendChild(tr.b.instantiateTemplate(
           '#x-sample-summary-panel-template', THIS_DOC));
 
       this.sampleType_ = undefined;
@@ -419,7 +419,7 @@
       }
 
       // Make it sortable.
-      tv.b.ui.SortableTable.decorate(table);
+      tr.b.ui.SortableTable.decorate(table);
 
       var calleeArea = that.querySelector('x-callees');
       calleeArea.textContent = '';
@@ -471,7 +471,7 @@
 
     getSamplesFromNode_: function(node) {
       // A node has samples associated with it, if it's a leaf node.
-      var selection = new tv.c.Selection();
+      var selection = new tr.c.Selection();
       if (node.leaf_node_id !== undefined) {
         selection.addSelection(this.stackFrameIdToSamples_[node.leaf_node_id]);
       }
@@ -496,7 +496,7 @@
 
       var sunburstData =
           createSunburstData(this.selection_, this.sampleType_);
-      this.chart_ = new tv.b.ui.SunburstChart();
+      this.chart_ = new tr.b.ui.SunburstChart();
       this.chart_.width = 600;
       this.chart_.height = 600;
       this.chart_.chartTitle = 'Sampling Summary';
@@ -546,7 +546,7 @@
         sampleTypeOptions.push({label: sampleTypes[i], value: sampleTypes[i]});
 
       var toolbarEl = this.querySelector('x-toolbar');
-      this.sampleTypeSelector_ = tv.b.ui.createSelector(
+      this.sampleTypeSelector_ = tr.b.ui.createSelector(
           this,
           'sampleType',
           'samplingSummaryPanel.sampleType',
diff --git a/trace-viewer/trace_viewer/extras/analysis/sampling_summary_test.html b/trace-viewer/trace_viewer/extras/analysis/sampling_summary_test.html
index 9489865..48648b4 100644
--- a/trace-viewer/trace_viewer/extras/analysis/sampling_summary_test.html
+++ b/trace-viewer/trace_viewer/extras/analysis/sampling_summary_test.html
@@ -7,20 +7,20 @@
 
 <link rel="import" href="/extras/analysis/sampling_summary.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var StackFrame = tv.c.trace_model.StackFrame;
-  var Sample = tv.c.trace_model.Sample;
+tr.b.unittest.testSuite(function() {
+  var StackFrame = tr.model.StackFrame;
+  var Sample = tr.model.Sample;
 
-  var newSliceEx = tv.c.test_utils.newSliceEx;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
 
   function createSelection() {
-    var selection = new tv.c.Selection();
-    var model = new tv.c.TraceModel();
+    var selection = new tr.c.Selection();
+    var model = new tr.Model();
     var thread = model.getOrCreateProcess(1).getOrCreateThread(2);
     thread.name = 'The Thread';
 
@@ -102,13 +102,13 @@
       ]
     };
 
-    var sunburstData = tv.e.analysis.createSunburstData(s, 'cycles');
+    var sunburstData = tr.e.analysis.createSunburstData(s, 'cycles');
     assert.equal(JSON.stringify(sunburstData), JSON.stringify(expect));
   });
 
   test('processOnlySamples', function() {
-    var selection = new tv.c.Selection();
-    var model = new tv.c.TraceModel();
+    var selection = new tr.c.Selection();
+    var model = new tr.Model();
     var thread = model.getOrCreateProcess(1).getOrCreateThread(2);
     thread.name = 'The Thread';
 
@@ -157,15 +157,15 @@
     // Along with the samples, push some slices too.
     // The panel should completely ignore these.
     selection.push(newSliceEx({
-      type: tv.c.trace_model.ThreadSlice,
+      type: tr.model.ThreadSlice,
       title: 'a', start: 1, duration: 2
     }));
     selection.push(newSliceEx({
-      type: tv.c.trace_model.ThreadSlice,
+      type: tr.model.ThreadSlice,
       title: 'f', start: 9, duration: 7
     }));
 
-    var sunburstData = tv.e.analysis.createSunburstData(
+    var sunburstData = tr.e.analysis.createSunburstData(
         selection, 'page_misses');
     assert.equal(JSON.stringify(sunburstData), JSON.stringify(expect));
   });
@@ -204,14 +204,14 @@
       ]
     };
 
-    var sunburstData = tv.e.analysis.createSunburstData(s, 'page_misses');
+    var sunburstData = tr.e.analysis.createSunburstData(s, 'page_misses');
     assert.equal(JSON.stringify(sunburstData), JSON.stringify(expect));
   });
 
   test('instantiate', function() {
     var s = createSelection();
 
-    var panel = new tv.e.analysis.SamplingSummaryPanel();
+    var panel = new tr.e.analysis.SamplingSummaryPanel();
     this.addHTMLOutput(panel);
     panel.style.border = '1px solid black';
     panel.selection = s;
diff --git a/trace-viewer/trace_viewer/extras/audits/android_app.html b/trace-viewer/trace_viewer/extras/android/android_app.html
similarity index 88%
rename from trace-viewer/trace_viewer/extras/audits/android_app.html
rename to trace-viewer/trace_viewer/extras/android/android_app.html
index 28c20c5..fb28c9c 100644
--- a/trace-viewer/trace_viewer/extras/audits/android_app.html
+++ b/trace-viewer/trace_viewer/extras/android/android_app.html
@@ -6,8 +6,8 @@
 -->
 <link rel="import" href="/base/statistics.html">
 <link rel="import" href="/base/sorted_array_utils.html">
-<link rel="import" href="/core/trace_model/frame.html">
-<link rel="import" href="/extras/audits/utils.html">
+<link rel="import" href="/model/frame.html">
+<link rel="import" href="/base/range_utils.html">
 
 <script>
 'use strict';
@@ -16,11 +16,14 @@
  * @fileoverview Class for managing android-specific model meta data,
  * such as rendering apps, and frames rendered.
  */
-tv.exportTo('tv.e.audits', function() {
-  var Frame = tv.c.trace_model.Frame;
-  var Statistics = tv.b.Statistics;
+tr.exportTo('tr.e.audits', function() {
+  var Frame = tr.model.Frame;
+  var Statistics = tr.b.Statistics;
 
-  var UI_THREAD_DRAW_NAME = 'performTraversals';
+  var UI_THREAD_DRAW_NAMES = {
+    'performTraversals': true,
+    'Choreographer#doFrame': true
+  };
   var RENDER_THREAD_DRAW_NAME = 'DrawFrame';
   var RENDER_THREAD_INDEP_DRAW_NAME = 'doFrame';
   var THREAD_SYNC_NAME = 'syncFrameState';
@@ -69,6 +72,8 @@
   /**
    * Builds an array of {start, end} ranges grouping common work of a frame
    * that occurs just before performTraversals().
+   *
+   * Only necessary before Choreographer#doFrame tracing existed.
    */
   function getPreTraversalWorkRanges(uiThread) {
     if (!uiThread)
@@ -79,7 +84,8 @@
     uiThread.sliceGroup.slices.forEach(function(slice) {
       if (slice.title == 'obtainView' ||
           slice.title == 'setupListItem' ||
-          slice.title == 'deliverInputEvent')
+          slice.title == 'deliverInputEvent' ||
+          slice.title == 'RV Scroll')
         preFrameEvents.push(slice);
     });
     uiThread.asyncSliceGroup.slices.forEach(function(slice) {
@@ -87,7 +93,7 @@
         preFrameEvents.push(slice);
     });
 
-    return tv.e.audits.mergeEvents(preFrameEvents, 3, function(events) {
+    return tr.e.audits.mergeExplicitRanges(preFrameEvents, 3, function(events) {
       return {
         start: events[0].start,
         end: events[events.length - 1].end
@@ -96,7 +102,7 @@
   }
 
   function getFrameStartTime(traversalStart, preTraversalWorkRanges) {
-    var preTraversalWorkRange = tv.b.findClosestIntervalInSortedIntervals(
+    var preTraversalWorkRange = tr.b.findClosestIntervalInSortedIntervals(
         preTraversalWorkRanges,
         function(range) { return range.start },
         function(range) { return range.end },
@@ -115,20 +121,23 @@
     var preTraversalWorkRanges = getPreTraversalWorkRanges(app.uiThread);
 
     var frames = [];
-    app.uiThread.sliceGroup.getSlicesOfName(UI_THREAD_DRAW_NAME)
-        .forEach(function(uiDrawSlice) {
+    app.uiThread.sliceGroup.slices.forEach(function(slice) {
+      if (!(slice.title in UI_THREAD_DRAW_NAMES)) {
+        return;
+      }
+
       var threadTimeRanges = [];
       var uiThreadTimeRange = {
         thread: app.uiThread,
-        start: getFrameStartTime(uiDrawSlice.start, preTraversalWorkRanges),
-        end: uiDrawSlice.end
+        start: getFrameStartTime(slice.start, preTraversalWorkRanges),
+        end: slice.end
       };
       threadTimeRanges.push(uiThreadTimeRange);
 
       // on SDK 21+ devices with RenderThread,
       // account for time taken on RenderThread
       var rtDrawSlice = findOverlappingDrawFrame(
-          app.renderThread, uiDrawSlice.end);
+          app.renderThread, slice.end);
       if (rtDrawSlice) {
         var rtSyncSlice = rtDrawSlice.findDescendentSlice(THREAD_SYNC_NAME);
         if (rtSyncSlice) {
@@ -169,8 +178,7 @@
   function hasUiDraw(uiThread) {
     var slices = uiThread.sliceGroup.slices;
     for (var i = 0; i < slices.length; i++) {
-      var slice = slices[i];
-      if (slice.title == UI_THREAD_DRAW_NAME) {
+      if (slices[i].title in UI_THREAD_DRAW_NAMES) {
         return uiThread;
       }
     }
diff --git a/trace-viewer/trace_viewer/extras/audits/android_auditor.html b/trace-viewer/trace_viewer/extras/android/android_auditor.html
similarity index 87%
rename from trace-viewer/trace_viewer/extras/audits/android_auditor.html
rename to trace-viewer/trace_viewer/extras/android/android_auditor.html
index 3f298b7..b01dc69 100644
--- a/trace-viewer/trace_viewer/extras/audits/android_auditor.html
+++ b/trace-viewer/trace_viewer/extras/android/android_auditor.html
@@ -6,13 +6,14 @@
 -->
 <link rel="import" href="/base/iteration_helpers.html">
 <link rel="import" href="/base/statistics.html">
-<link rel="import" href="/base/time.html">
+<link rel="import" href="/base/units/time_duration.html">
+<link rel="import" href="/base/units/time_stamp.html">
 <link rel="import" href="/core/auditor.html">
-<link rel="import" href="/core/trace_model/alert.html">
-<link rel="import" href="/core/trace_model/frame.html">
-<link rel="import" href="/core/trace_model/interaction_record.html">
-<link rel="import" href="/extras/audits/android_model_helper.html">
-<link rel="import" href="/extras/audits/utils.html">
+<link rel="import" href="/model/alert.html">
+<link rel="import" href="/model/frame.html">
+<link rel="import" href="/model/interaction_record.html">
+<link rel="import" href="/extras/android/android_model_helper.html">
+<link rel="import" href="/base/range_utils.html">
 
 <script>
 'use strict';
@@ -20,16 +21,16 @@
 /**
  * @fileoverview Class for Android-specific Auditing.
  */
-tv.exportTo('tv.e.audits', function() {
-  var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
-  var Auditor = tv.c.Auditor;
-  var AndroidModelHelper = tv.e.audits.AndroidModelHelper;
-  var Statistics = tv.b.Statistics;
-  var FRAME_PERF_CLASS = tv.c.trace_model.FRAME_PERF_CLASS;
-  var InteractionRecord = tv.c.trace_model.InteractionRecord;
-  var Alert = tv.c.trace_model.Alert;
-  var EventInfo = tv.c.trace_model.EventInfo;
-  var TimeDuration = tv.b.TimeDuration;
+tr.exportTo('tr.e.audits', function() {
+  var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+  var Auditor = tr.c.Auditor;
+  var AndroidModelHelper = tr.e.audits.AndroidModelHelper;
+  var Statistics = tr.b.Statistics;
+  var FRAME_PERF_CLASS = tr.model.FRAME_PERF_CLASS;
+  var InteractionRecord = tr.model.InteractionRecord;
+  var Alert = tr.model.Alert;
+  var EventInfo = tr.model.EventInfo;
+  var TimeDuration = tr.b.units.TimeDuration;
 
   // TODO: extract from VSYNC, since not all devices have vsync near 60fps
   var EXPECTED_FRAME_TIME_MS = 16.67;
@@ -48,12 +49,9 @@
     }
     return false;
   }
-  // TODO: use sane values or different metric
-  var MAX_TIME_UNSCHEDULED = 3.0;
-  var MAX_TIME_BLOCKING_IO = 5.0;
 
-  var Auditor = tv.c.Auditor;
-  var AndroidModelHelper = tv.e.audits.AndroidModelHelper;
+  var Auditor = tr.c.Auditor;
+  var AndroidModelHelper = tr.e.audits.AndroidModelHelper;
 
   function frameMissedDeadline(frame) {
     return frame.args['deadline'] && frame.args['deadline'] < frame.end;
@@ -234,7 +232,7 @@
     // TODO(ccraik): make 'inflate' slices associated events.
     var hasInflation = false;
     for (var i = 0; i < events.length; i++) {
-      if (events[i] instanceof tv.c.trace_model.Slice &&
+      if (events[i] instanceof tr.model.Slice &&
           events[i].findDescendentSlice('inflate')) {
         hasInflation = true;
         break;
@@ -346,13 +344,13 @@
 
   AndroidAuditor.schedulingAlertInfo_ = new EventInfo(
       'Scheduling delay',
-      'Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should with a priority number of 130 or higher in the scheduling section under the Kernel process.'); // @suppress longLineCheck
+      'Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.'); // @suppress longLineCheck
   AndroidAuditor.getSchedulingAlert_ = function(frame) {
     var totalDuration = 0;
     var totalStats = {};
     frame.threadTimeRanges.forEach(function(ttr) {
       var stats = ttr.thread.getSchedulingStatsForRange(ttr.start, ttr.end);
-      tv.b.iterItems(stats, function(key, value) {
+      tr.b.iterItems(stats, function(key, value) {
         if (!(key in totalStats))
           totalStats[key] = 0;
         totalStats[key] += value;
@@ -368,7 +366,7 @@
       return;
 
     var args = {};
-    tv.b.iterItems(totalStats, function(key, value) {
+    tr.b.iterItems(totalStats, function(key, value) {
       if (key === SCHEDULING_STATE.RUNNABLE)
         key = 'Not scheduled, but runnable';
       else if (key === SCHEDULING_STATE.UNINTR_SLEEP)
@@ -534,12 +532,12 @@
 
       var mergerFunction = function(events) {
         var ir = new InteractionRecord('Rendering',
-            tv.b.ui.getColorIdForGeneralPurposeString('mt_rendering'),
+            tr.b.ui.getColorIdForGeneralPurposeString('mt_rendering'),
             events[0].start,
             events[events.length - 1].end - events[0].start);
         this.model.addInteractionRecord(ir);
       }.bind(this);
-      tv.e.audits.mergeEvents(events, 30, mergerFunction);
+      tr.e.audits.mergeExplicitRanges(events, 30, mergerFunction);
     },
 
     addInputInteractionRecords: function() {
@@ -550,13 +548,13 @@
 
       var mergerFunction = function(events) {
         var ir = new InteractionRecord('Input',
-            tv.b.ui.getColorIdForGeneralPurposeString('mt_input'),
+            tr.b.ui.getColorIdForGeneralPurposeString('mt_input'),
             events[0].timestamp,
             events[events.length - 1].timestamp - events[0].timestamp);
         this.model.addInteractionRecord(ir);
       }.bind(this);
       var timestampFunction = function(x) { return x.timestamp; };
-      tv.e.audits.mergeEvents(inputSamples, 30, mergerFunction,
+      tr.e.audits.mergeExplicitRanges(inputSamples, 30, mergerFunction,
                               timestampFunction, timestampFunction);
     }
   };
@@ -574,8 +572,8 @@
       var registerEventInfo = function(dict) {
         this.titleInfoLookup[dict.title] = new EventInfo(
             dict.title, dict.description, dict.docLinks);
-        if (dict.parent)
-          this.titleParentLookup[dict.title] = dict.parent;
+        if (dict.parents)
+          this.titleParentLookup[dict.title] = dict.parents;
       }.bind(this);
 
       registerEventInfo({
@@ -596,41 +594,71 @@
           description: 'Attached a newly-bound, recycled View to its parent GridView.'}); // @suppress longLineCheck
 
       //////////////////////////////////////////////////////////////////////////
+      // Choreographer (tracing enabled on M+)
+      //////////////////////////////////////////////////////////////////////////
+      var choreographerLinks = new DocLinkBuilder()
+          .addDacRef('Choreographer', 'android/view/Choreographer.html') // @suppress longLineCheck
+          .build();
+      registerEventInfo({
+          title: 'Choreographer#doFrame',
+          docLinks: choreographerLinks,
+          description: 'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'}); // @suppress longLineCheck
+      registerEventInfo({
+          title: 'input',
+          parents: ['Choreographer#doFrame'],
+          docLinks: choreographerLinks,
+          description: 'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'}); // @suppress longLineCheck
+      registerEventInfo({
+          title: 'animation',
+          parents: ['Choreographer#doFrame'],
+          docLinks: choreographerLinks,
+          description: 'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'}); // @suppress longLineCheck
+      registerEventInfo({
+          title: 'traversals',
+          parents: ['Choreographer#doFrame'],
+          docLinks: choreographerLinks,
+          description: 'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'}); // @suppress longLineCheck
+
+      //////////////////////////////////////////////////////////////////////////
       // performTraversals + sub methods
       //////////////////////////////////////////////////////////////////////////
+      var traversalParents = ['Choreographer#doFrame', 'performTraversals'];
+      var layoutLinks = new DocLinkBuilder()
+          .addDacRef('View#Layout', 'android/view/View.html#Layout')
+          .build();
       registerEventInfo({
           title: 'performTraversals',
           description: 'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'}); // @suppress longLineCheck
       registerEventInfo({
           title: 'measure',
-          parent: 'performTraversals',
-          docLinks: {'View#layout documentation': 'https://developer.android.com/reference/android/view/View.html#Layout'}, // @suppress longLineCheck
+          parents: traversalParents,
+          docLinks: layoutLinks,
           description: 'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'}); // @suppress longLineCheck
       registerEventInfo({
           title: 'layout',
-          parent: 'performTraversals',
-          docLinks: {'View#layout documentation': 'https://developer.android.com/reference/android/view/View.html#Layout'}, // @suppress longLineCheck
+          parents: traversalParents,
+          docLinks: layoutLinks,
           description: 'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'}); // @suppress longLineCheck
+      var drawString = 'Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.'; // @suppress longLineCheck
       registerEventInfo({
           title: 'draw',
-          parent: 'performTraversals',
-          description: 'Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.'}); // @suppress longLineCheck
+          parents: traversalParents,
+          description: drawString});
 
       var recordString = 'Every invalidated View\'s drawing commands are recorded. Each will have View#draw() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.'; // @suppress longLineCheck
       registerEventInfo({
           title: 'getDisplayList', // Legacy name for compatibility.
-          parent: 'draw',
+          parents: ['draw'],
           description: recordString});
       registerEventInfo({
           title: 'Record View#draw()',
-          parent: 'draw',
+          parents: ['draw'],
           description: recordString});
 
-
       registerEventInfo({
           title: 'drawDisplayList',
-          parent: 'draw',
-          description: 'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU.'}); // @suppress longLineCheck
+          parents: ['draw'],
+          description: 'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'}); // @suppress longLineCheck
 
       //////////////////////////////////////////////////////////////////////////
       // RenderThread
@@ -683,10 +711,18 @@
     },
 
     applyEventInfosRecursive_: function(parentNames, slice) {
+      var checkExpectedParentNames = function(expectedParentNames) {
+        if (!expectedParentNames)
+          return true;
+        return expectedParentNames.some(function(name) {
+          return name in parentNames;
+        });
+      }
+
+
       // Set EventInfo on the slice if it matches title, and parent.
       if (slice.title in this.titleInfoLookup) {
-        var expectedParentName = this.titleParentLookup[slice.title];
-        if (!expectedParentName || expectedParentName in parentNames)
+        if (checkExpectedParentNames(this.titleParentLookup[slice.title]))
           slice.info = this.titleInfoLookup[slice.title];
       }
 
diff --git a/trace-viewer/trace_viewer/extras/audits/android_auditor_test.html b/trace-viewer/trace_viewer/extras/android/android_auditor_test.html
similarity index 81%
rename from trace-viewer/trace_viewer/extras/audits/android_auditor_test.html
rename to trace-viewer/trace_viewer/extras/android/android_auditor_test.html
index a9aea96..253a23d 100644
--- a/trace-viewer/trace_viewer/extras/audits/android_auditor_test.html
+++ b/trace-viewer/trace_viewer/extras/android/android_auditor_test.html
@@ -5,24 +5,23 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/base/time.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/frame.html">
-<link rel="import" href="/extras/audits/android_auditor.html">
+<link rel="import" href="/model/frame.html">
+<link rel="import" href="/extras/android/android_auditor.html">
 <link rel="import" href="/extras/importer/linux_perf/ftrace_importer.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-  var FRAME_PERF_CLASS = tv.c.trace_model.FRAME_PERF_CLASS;
-  var newThreadSlice = tv.c.test_utils.newThreadSlice;
-  var TimeDuration = tv.b.TimeDuration;
+tr.b.unittest.testSuite(function() {
+  var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+  var FRAME_PERF_CLASS = tr.model.FRAME_PERF_CLASS;
+  var newThreadSlice = tr.c.test_utils.newThreadSlice;
+  var TimeDuration = tr.b.units.TimeDuration;
 
   test('saveLayerAlert_badAlpha', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
       renderThread.name = 'RenderThread';
       renderThread.sliceGroup.pushSlice(newSliceNamed('doFrame', 200, 5));
@@ -32,7 +31,7 @@
       // doesn't create alert, since bad alpha accounts for this savelayer
       renderThread.sliceGroup.pushSlice(newSliceNamed(
           'unclipped saveLayer 480x320', 204, 1));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 1);
 
@@ -43,13 +42,13 @@
   });
 
   test('saveLayerAlert_canvas', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
       renderThread.name = 'RenderThread';
       renderThread.sliceGroup.pushSlice(newSliceNamed('doFrame', 200, 5));
       renderThread.sliceGroup.pushSlice(newSliceNamed(
           'saveLayer 480x320', 204, 1));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 1);
 
@@ -59,7 +58,7 @@
   });
 
   test('generatePathAlert', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
       renderThread.name = 'RenderThread';
       renderThread.sliceGroup.pushSlice(newSliceNamed('doFrame', 0, 20));
@@ -67,7 +66,7 @@
           'Generate Path Texture', 0, 3));
       renderThread.sliceGroup.pushSlice(newSliceNamed(
           'Generate Path Texture', 3, 6));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 1);
 
@@ -77,13 +76,13 @@
   });
 
   test('uploadAlert', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
       renderThread.name = 'RenderThread';
       renderThread.sliceGroup.pushSlice(newSliceNamed('doFrame', 0, 20));
       renderThread.sliceGroup.pushSlice(newSliceNamed(
           'Upload 1000x1000 Texture', 0, 15));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 1);
 
@@ -94,7 +93,7 @@
   });
 
   test('listViewAlert', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       uiThread.sliceGroup.pushSlice(newSliceNamed('obtainView', 0, 5));
       uiThread.sliceGroup.pushSlice(newSliceNamed('setupListItem', 5, 5));
@@ -111,7 +110,7 @@
       uiThread.sliceGroup.pushSlice(newSliceNamed('inflate', 101, 8));
       uiThread.sliceGroup.pushSlice(newSliceNamed('setupListItem', 110, 10));
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 120, 5));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 2);
     var alert = model.alerts[0];
@@ -126,12 +125,12 @@
   });
 
   test('measureLayoutAlert', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 0, 20));
       uiThread.sliceGroup.pushSlice(newSliceNamed('measure', 0, 5));
       uiThread.sliceGroup.pushSlice(newSliceNamed('layout', 10, 5));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 1);
 
@@ -141,7 +140,7 @@
   });
 
   test('viewDrawAlert', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       // modern naming
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 0, 20));
@@ -150,7 +149,7 @@
       // legacy naming
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 40, 20));
       uiThread.sliceGroup.pushSlice(newSliceNamed('getDisplayList', 40, 10));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 2);
     assert.deepEqual(model.alerts[0].args['Time spent'], new TimeDuration(10));
@@ -158,7 +157,7 @@
   });
 
   test('blockingGcAlert', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       var sliceGroup = uiThread.sliceGroup;
       sliceGroup.pushSlice(newSliceNamed('performTraversals', 0, 20));
@@ -166,7 +165,7 @@
 
       sliceGroup.pushSlice(newSliceNamed('performTraversals', 50, 20));
       sliceGroup.pushSlice(newSliceNamed('GC: Wait For Concurrent', 50, 15));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 2);
     assert.deepEqual(model.alerts[0].args['Blocked duration'],
@@ -176,12 +175,12 @@
   });
 
   test('lockContentionAlert', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       var sliceGroup = uiThread.sliceGroup;
       sliceGroup.pushSlice(newSliceNamed('performTraversals', 0, 20));
       sliceGroup.pushSlice(newSliceNamed('Lock Contention on a lock', 0, 15));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(model.alerts.length, 1);
     assert.deepEqual(model.alerts[0].args['Blocked duration'],
@@ -189,43 +188,50 @@
   });
 
   test('schedulingAlerts', function() {
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 0, 20));
       uiThread.timeSlices = [
           newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 0, 6),
           newThreadSlice(uiThread, SCHEDULING_STATE.RUNNABLE, 6, 10),
           newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 16, 4)];
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
     assert.equal(model.alerts.length, 1);
     var alert = model.alerts[0];
     assert.equal(alert.info.title, 'Scheduling delay');
     assert.deepEqual(alert.args['Not scheduled, but runnable'],
         new TimeDuration(10));
 
-    model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 0, 20));
       uiThread.timeSlices = [
           newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 0, 5),
           newThreadSlice(uiThread, SCHEDULING_STATE.UNINTR_SLEEP, 5, 10),
           newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 15, 5)];
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
     assert.equal(model.alerts.length, 1);
     var alert = model.alerts[0];
     assert.equal(alert.info.title, 'Scheduling delay');
     assert.deepEqual(alert.args['Blocking I/O delay'], new TimeDuration(10));
   });
 
-  test('addFrameToModel', function() {
+  test('addFramesToModel', function() {
     var process;
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       process = model.getOrCreateProcess(1);
       var uiThread = process.getOrCreateThread(1);
-      uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 0, 8));
-      uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 16, 20));
-      uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 40, 90));
-    }, tv.e.audits.AndroidAuditor);
+
+      // High level choreographer frame signal
+      uiThread.sliceGroup.pushSlice(newSliceNamed(
+          'Choreographer#doFrame', 0, 8));
+      uiThread.sliceGroup.pushSlice(newSliceNamed(
+          'Choreographer#doFrame', 16, 20));
+
+      // Old devices only have 'performTraversals'
+      uiThread.sliceGroup.pushSlice(newSliceNamed(
+          'performTraversals', 40, 90));
+    }, tr.e.audits.AndroidAuditor);
 
     assert.equal(process.frames.length, 3);
     assert.closeTo(process.frames[0].totalDuration, 8, 1e-5);
@@ -243,7 +249,7 @@
   test('processRenameAndSort', function() {
     var appProcess;
     var sfProcess;
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       appProcess = model.getOrCreateProcess(1);
       var uiThread = appProcess.getOrCreateThread(1);
       uiThread.name = 'ndroid.systemui';
@@ -254,7 +260,7 @@
       sfThread.name = '/system/bin/surfaceflinger';
       sfThread.sliceGroup.pushSlice(newSliceNamed('doComposition', 8, 2));
 
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     // both processes should be renamed
     assert.equal(appProcess.name, 'android.systemui');
@@ -269,7 +275,7 @@
     var eventsExpectingInfo = [];
     var eventsNotExpectingInfo = [];
 
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var appProcess = model.getOrCreateProcess(1);
       var uiThread = appProcess.getOrCreateThread(1);
       uiThread.name = 'ndroid.systemui';
@@ -291,7 +297,7 @@
       // Out of place slices should not be tagged.
       pushNonInfoSlice(newSliceNamed('measure', 11, 1));
       pushNonInfoSlice(newSliceNamed('draw', 12, 1));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     eventsExpectingInfo.forEach(function(event) {
       assert.notEqual(event.info, undefined);
@@ -307,7 +313,7 @@
     var renderThread;
     var workerThread;
     var otherThread;
-    var model = tv.c.test_utils.newModelWithAuditor(function(model) {
+    var model = tr.c.test_utils.newModelWithAuditor(function(model) {
       var appProcess = model.getOrCreateProcess(1);
 
       uiThread = appProcess.getOrCreateThread(1);
@@ -325,7 +331,7 @@
       otherThread = appProcess.getOrCreateThread(4);
       otherThread.name = 'other';
       otherThread.sliceGroup.pushSlice(newSliceNamed('otherWork', 0, 2));
-    }, tv.e.audits.AndroidAuditor);
+    }, tr.e.audits.AndroidAuditor);
 
     assert.isTrue(uiThread.sortIndex < renderThread.sortIndex);
     assert.isTrue(renderThread.sortIndex < workerThread.sortIndex);
@@ -333,9 +339,9 @@
   });
 
   test('favicon', function() {
-    var createTraceModelWithJank = function(percentageJank) {
+    var createModelWithJank = function(percentageJank) {
 
-      return tv.c.test_utils.newModelWithAuditor(function(model) {
+      return tr.c.test_utils.newModelWithAuditor(function(model) {
         var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
         for (var i = 0; i < 100; i++) {
           var slice = newSliceNamed('performTraversals',
@@ -343,11 +349,11 @@
                                     i <= percentageJank ? 24 : 8);
           uiThread.sliceGroup.pushSlice(slice);
         }
-      }, tv.e.audits.AndroidAuditor);
+      }, tr.e.audits.AndroidAuditor);
     };
-    assert.equal(createTraceModelWithJank(3).faviconHue, 'green');
-    assert.equal(createTraceModelWithJank(10).faviconHue, 'yellow');
-    assert.equal(createTraceModelWithJank(50).faviconHue, 'red');
+    assert.equal(createModelWithJank(3).faviconHue, 'green');
+    assert.equal(createModelWithJank(10).faviconHue, 'yellow');
+    assert.equal(createModelWithJank(50).faviconHue, 'red');
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/extras/audits/android_model_helper.html b/trace-viewer/trace_viewer/extras/android/android_model_helper.html
similarity index 86%
rename from trace-viewer/trace_viewer/extras/audits/android_model_helper.html
rename to trace-viewer/trace_viewer/extras/android/android_model_helper.html
index d2f3ce3..a10628c 100644
--- a/trace-viewer/trace_viewer/extras/audits/android_model_helper.html
+++ b/trace-viewer/trace_viewer/extras/android/android_model_helper.html
@@ -6,9 +6,9 @@
 -->
 <link rel="import" href="/base/base.html">
 <link rel="import" href="/core/auditor.html">
-<link rel="import" href="/extras/audits/android_app.html">
-<link rel="import" href="/extras/audits/android_surface_flinger.html">
-<link rel="import" href="/extras/audits/utils.html">
+<link rel="import" href="/extras/android/android_app.html">
+<link rel="import" href="/extras/android/android_surface_flinger.html">
+<link rel="import" href="/base/range_utils.html">
 
 <script>
 'use strict';
@@ -17,9 +17,9 @@
  * @fileoverview Class for managing android-specific model meta data,
  * such as rendering apps, frames rendered, and SurfaceFlinger.
  */
-tv.exportTo('tv.e.audits', function() {
-  var AndroidApp = tv.e.audits.AndroidApp;
-  var AndroidSurfaceFlinger = tv.e.audits.AndroidSurfaceFlinger;
+tr.exportTo('tr.e.audits', function() {
+  var AndroidApp = tr.e.audits.AndroidApp;
+  var AndroidSurfaceFlinger = tr.e.audits.AndroidSurfaceFlinger;
 
   var IMPORTANT_SURFACE_FLINGER_SLICES = {
     'doComposition' : true,
@@ -27,6 +27,7 @@
     'postFramebuffer' : true
   };
   var IMPORTANT_UI_THREAD_SLICES = {
+    'Choreographer#doFrame' : true,
     'performTraversals' : true,
     'deliverInputEvent' : true
   };
diff --git a/trace-viewer/trace_viewer/extras/audits/android_model_helper_test.html b/trace-viewer/trace_viewer/extras/android/android_model_helper_test.html
similarity index 86%
rename from trace-viewer/trace_viewer/extras/audits/android_model_helper_test.html
rename to trace-viewer/trace_viewer/extras/android/android_model_helper_test.html
index b160fcf..4b3c64f 100644
--- a/trace-viewer/trace_viewer/extras/audits/android_model_helper_test.html
+++ b/trace-viewer/trace_viewer/extras/android/android_model_helper_test.html
@@ -6,19 +6,19 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/extras/audits/android_auditor.html">
+<link rel="import" href="/extras/android/android_auditor.html">
 <link rel="import" href="/extras/importer/linux_perf/ftrace_importer.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var AndroidModelHelper = tv.e.audits.AndroidModelHelper;
-  var TraceModel = tv.c.TraceModel;
-  var newAsyncSliceNamed = tv.c.test_utils.newAsyncSliceNamed;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-  var newCounterNamed = tv.c.test_utils.newCounterNamed;
-  var newCounterSeries = tv.c.test_utils.newCounterSeries;
+tr.b.unittest.testSuite(function() {
+  var AndroidModelHelper = tr.e.audits.AndroidModelHelper;
+  var newAsyncSliceNamed = tr.c.test_utils.newAsyncSliceNamed;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
+  var newCounterNamed = tr.c.test_utils.newCounterNamed;
+  var newCounterSeries = tr.c.test_utils.newCounterSeries;
 
   function createSurfaceFlingerWithVsyncs(model) {
       if (model.getProcess(2))
@@ -29,7 +29,11 @@
       sfThread.name = '/system/bin/surfaceflinger';
 
       // ensure slicegroup has data
-      sfThread.sliceGroup.pushSlice(newSliceNamed('doComposition', 8, 2));
+      sfThread.sliceGroup.pushSlice(newSliceEx({
+        title: 'doComposition',
+        start: 8,
+        duration: 2
+      }));
 
       var counter = sfProcess.getOrCreateCounter('android', 'VSYNC');
       var series = newCounterSeries();
@@ -84,7 +88,7 @@
 
   test('getThreads', function() {
     SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) {
-      var model = tv.c.test_utils.newModel(customizeModelCallback);
+      var model = tr.c.test_utils.newModel(customizeModelCallback);
       var helper = new AndroidModelHelper(model);
       assert.equal(helper.apps[0].uiThread, model.uiThread);
       assert.equal(helper.apps[0].renderThread, model.renderThread);
@@ -93,12 +97,12 @@
 
   test('iterateImportantSlices', function() {
     SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) {
-      var model = tv.c.test_utils.newModel(customizeModelCallback);
+      var model = tr.c.test_utils.newModel(customizeModelCallback);
       var helper = new AndroidModelHelper(model);
 
       var seen = 0;
       helper.iterateImportantSlices(function(importantSlice) {
-        assert.isTrue(importantSlice instanceof tv.c.trace_model.Slice);
+        assert.isTrue(importantSlice instanceof tr.model.Slice);
         seen++;
       });
       assert.equal(seen, 1);
@@ -107,7 +111,7 @@
 
   test('getFrames', function() {
     SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) {
-      var model = tv.c.test_utils.newModel(customizeModelCallback);
+      var model = tr.c.test_utils.newModel(customizeModelCallback);
       var helper = new AndroidModelHelper(model);
       assert.equal(helper.apps.length, 1);
 
@@ -121,7 +125,7 @@
   });
 
   test('surfaceFlingerVsyncs', function() {
-    var model = tv.c.test_utils.newModel(createSurfaceFlingerWithVsyncs);
+    var model = tr.c.test_utils.newModel(createSurfaceFlingerWithVsyncs);
     var helper = new AndroidModelHelper(model);
     assert.isTrue(helper.surfaceFlinger.hasVsyncs);
 
@@ -138,7 +142,7 @@
   });
 
   test('frameVsyncInterop', function() {
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       // app - 3 good, 3 bad frames
       var uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 1, 8));
@@ -163,7 +167,7 @@
   });
 
   test('appInputs', function() {
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       var process = model.getOrCreateProcess(120);
       var uiThread = process.getOrCreateThread(120);
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 20, 4));
@@ -189,7 +193,7 @@
   });
 
   test('appAnimations', function() {
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       var process = model.getOrCreateProcess(120);
       var uiThread = process.getOrCreateThread(120);
       uiThread.sliceGroup.pushSlice(newSliceNamed('performTraversals', 10, 10));
diff --git a/trace-viewer/trace_viewer/extras/audits/android_surface_flinger.html b/trace-viewer/trace_viewer/extras/android/android_surface_flinger.html
similarity index 96%
rename from trace-viewer/trace_viewer/extras/audits/android_surface_flinger.html
rename to trace-viewer/trace_viewer/extras/android/android_surface_flinger.html
index 854f725..7bd6a36 100644
--- a/trace-viewer/trace_viewer/extras/audits/android_surface_flinger.html
+++ b/trace-viewer/trace_viewer/extras/android/android_surface_flinger.html
@@ -13,8 +13,8 @@
 /**
  * @fileoverview Class for representing SurfaceFlinger process and its Vsyncs.
  */
-tv.exportTo('tv.e.audits', function() {
-  var findLowIndexInSortedArray = tv.b.findLowIndexInSortedArray;
+tr.exportTo('tr.e.audits', function() {
+  var findLowIndexInSortedArray = tr.b.findLowIndexInSortedArray;
 
   var VSYNC_SF_NAME = 'android.VSYNC-sf';
   var VSYNC_APP_NAME = 'android.VSYNC-app';
diff --git a/trace-viewer/trace_viewer/extras/audits/utils.html b/trace-viewer/trace_viewer/extras/audits/utils.html
deleted file mode 100644
index 7d7e584..0000000
--- a/trace-viewer/trace_viewer/extras/audits/utils.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 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="import" href="/base/base.html">
-<link rel="import" href="/base/iteration_helpers.html">
-<script>
-'use strict';
-
-/**
- * @fileoverview Provides event merging functionality for grouping/analysis.
- */
-tv.exportTo('tv.e.audits', function() {
-
-  function mergeEvents(inEvents, mergeThreshold, mergeFunction,
-                       opt_startFunction, opt_endFunction) {
-    var startFunction = opt_startFunction;
-    var endFunction = opt_endFunction;
-    if (!startFunction)
-      startFunction = function(event) { return event.start; };
-    if (!endFunction)
-      endFunction = function(event) { return event.end; };
-
-    var remainingEvents = inEvents.slice();
-    remainingEvents.sort(function(x, y) {
-      return startFunction(x) - startFunction(y);
-    });
-
-    if (remainingEvents.length <= 1) {
-      var merged = [];
-      if (remainingEvents.length == 1) {
-        merged.push(mergeFunction(remainingEvents));
-      }
-      return merged;
-    }
-
-    var mergedEvents = [];
-
-    var currentMergeBuffer = [];
-    var rightEdge;
-    function beginMerging() {
-      currentMergeBuffer.push(remainingEvents[0]);
-      remainingEvents.splice(0, 1);
-      rightEdge = endFunction(currentMergeBuffer[0]);
-    }
-
-    function flushCurrentMergeBuffer() {
-      if (currentMergeBuffer.length == 0)
-        return;
-
-      mergedEvents.push(mergeFunction(currentMergeBuffer));
-      currentMergeBuffer = [];
-
-      // Refill merge buffer if needed.
-      if (remainingEvents.length != 0)
-        beginMerging();
-    }
-
-    beginMerging();
-
-    while (remainingEvents.length) {
-      var currentEvent = remainingEvents[0];
-
-      var distanceFromRightEdge = startFunction(currentEvent) - rightEdge;
-      if (distanceFromRightEdge < mergeThreshold) {
-        rightEdge = Math.max(rightEdge, endFunction(currentEvent));
-        remainingEvents.splice(0, 1);
-        currentMergeBuffer.push(currentEvent);
-        continue;
-      }
-
-      // Too big a gap.
-      flushCurrentMergeBuffer();
-    }
-    flushCurrentMergeBuffer();
-
-    return mergedEvents;
-  }
-
-  return {
-    mergeEvents: mergeEvents
-  };
-});
-</script>
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/constants.html b/trace-viewer/trace_viewer/extras/chrome/cc/constants.html
index 9b7a7da..a42c099 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/constants.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/constants.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var constants = {};
   constants.ACTIVE_TREE = 0;
   constants.PENDING_TREE = 1;
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/debug_colors.html b/trace-viewer/trace_viewer/extras/chrome/cc/debug_colors.html
index 87c2dba..4f91689 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/debug_colors.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/debug_colors.html
@@ -12,7 +12,7 @@
  * @fileoverview Mapping of different tile configuration
  * to border colors and widths.
  */
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var tileTypes = {
     highRes: 'highRes',
     lowRes: 'lowRes',
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger.html b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger.html
index 4f9f2e2..eeba731 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger.html
@@ -127,7 +127,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
   /**
@@ -136,13 +136,13 @@
    *
    * @constructor
    */
-  var DisplayItemDebugger = tv.b.ui.define('display-item-debugger');
+  var DisplayItemDebugger = tr.b.ui.define('display-item-debugger');
 
   DisplayItemDebugger.prototype = {
     __proto__: HTMLUnknownElement.prototype,
 
     decorate: function() {
-      var node = tv.b.instantiateTemplate('#display-item-debugger-template',
+      var node = tr.b.instantiateTemplate('#display-item-debugger-template',
           THIS_DOC);
 
       this.appendChild(node);
@@ -161,7 +161,7 @@
       this.displayItemInfo_.addEventListener(
           'click', this.onDisplayItemInfoClick_.bind(this), false);
 
-      this.displayItemListView_ = new tv.b.ui.ListView();
+      this.displayItemListView_ = new tr.b.ui.ListView();
       this.displayItemListView_.addEventListener('selection-changed',
           this.onDisplayItemListSelection_.bind(this));
       this.displayItemInfo_.appendChild(this.displayItemListView_);
@@ -178,23 +178,23 @@
 
       var leftPanel = this.querySelector('left-panel');
 
-      var middleDragHandle = new tv.b.ui.DragHandle();
+      var middleDragHandle = new tr.b.ui.DragHandle();
       middleDragHandle.horizontal = false;
       middleDragHandle.target = leftPanel;
 
       var rightPanel = this.querySelector('right-panel');
 
-      this.infoBar_ = document.createElement('tv-b-ui-info-bar');
+      this.infoBar_ = document.createElement('tr-b-ui-info-bar');
       this.rasterArea_.insertBefore(this.infoBar_, this.rasterCanvas_);
 
       this.insertBefore(middleDragHandle, rightPanel);
 
       this.picture_ = undefined;
 
-      this.pictureOpsListView_ = new tv.e.cc.PictureOpsListView();
+      this.pictureOpsListView_ = new tr.e.cc.PictureOpsListView();
       rightPanel.insertBefore(this.pictureOpsListView_, this.rasterArea_);
 
-      this.pictureOpsListDragHandle_ = new tv.b.ui.DragHandle();
+      this.pictureOpsListDragHandle_ = new tr.b.ui.DragHandle();
       this.pictureOpsListDragHandle_.horizontal = false;
       this.pictureOpsListDragHandle_.target = this.pictureOpsListView_;
       rightPanel.insertBefore(this.pictureOpsListDragHandle_, this.rasterArea_);
@@ -262,7 +262,7 @@
       if (this.updateContentsPending_)
         return;
       this.updateContentsPending_ = true;
-      tv.b.requestAnimationFrameInThisFrameIfPossible(
+      tr.b.requestAnimationFrameInThisFrameIfPossible(
           this.updateContents_.bind(this)
       );
     },
@@ -285,7 +285,7 @@
       if (this.pictureAsImageData_.error) {
         this.infoBar_.message = 'Cannot rasterize...';
         this.infoBar_.addButton('More info...', function(e) {
-          var overlay = new tv.b.ui.Overlay();
+          var overlay = new tr.b.ui.Overlay();
           overlay.textContent = this.pictureAsImageData_.error;
           overlay.visible = true;
           e.stopPropagation();
@@ -344,7 +344,7 @@
           this.displayItemListView_.children, selected);
       var displayItem = this.displayItemList_.items[index];
       if (displayItem && displayItem.skp64)
-        this.picture = new tv.e.cc.Picture(
+        this.picture = new tr.e.cc.Picture(
             displayItem.skp64, this.displayItemList_.layerRect);
       else
         this.picture = undefined;
@@ -370,13 +370,13 @@
     },
 
     trackMouse_: function() {
-      this.mouseModeSelector_ = new tv.b.ui.MouseModeSelector(this.rasterArea_);
+      this.mouseModeSelector_ = new tr.b.ui.MouseModeSelector(this.rasterArea_);
       this.rasterArea_.appendChild(this.mouseModeSelector_);
 
       this.mouseModeSelector_.supportedModeMask =
-          tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
-      this.mouseModeSelector_.mode = tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
-      this.mouseModeSelector_.defaultMode = tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
+          tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
+      this.mouseModeSelector_.mode = tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
+      this.mouseModeSelector_.defaultMode = tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
       this.mouseModeSelector_.settingsKey = 'pictureDebugger.mouseModeSelector';
 
       this.mouseModeSelector_.addEventListener('beginzoom',
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger_test.html
index 711d223..1ecfc6b 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_debugger_test.html
@@ -11,9 +11,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
-    var displayItemList = new tv.e.cc.DisplayItemListSnapshot(
+    var displayItemList = new tr.e.cc.DisplayItemListSnapshot(
       {id: '31415'},
       10,
       {
@@ -28,7 +28,7 @@
     displayItemList.preInitialize();
     displayItemList.initialize();
 
-    var dbg = new tv.e.cc.DisplayItemDebugger();
+    var dbg = new tr.e.cc.DisplayItemDebugger();
     this.addHTMLOutput(dbg);
     assert.isUndefined(dbg.displayItemList_);
     assert.isUndefined(dbg.picture_);
@@ -40,7 +40,7 @@
   });
 
   test('selections', function() {
-    var displayItemList = new tv.e.cc.DisplayItemListSnapshot(
+    var displayItemList = new tr.e.cc.DisplayItemListSnapshot(
       {id: '31415'},
       10,
       {
@@ -58,7 +58,7 @@
     displayItemList.preInitialize();
     displayItemList.initialize();
 
-    var dbg = new tv.e.cc.DisplayItemDebugger();
+    var dbg = new tr.e.cc.DisplayItemDebugger();
     this.addHTMLOutput(dbg);
     dbg.displayItemList = displayItemList;
     assert.isDefined(dbg.displayItemList_);
@@ -89,7 +89,7 @@
   });
 
   test('export', function() {
-    var displayItemList = new tv.e.cc.DisplayItemListSnapshot(
+    var displayItemList = new tr.e.cc.DisplayItemListSnapshot(
       {id: '31415'},
       10,
       {
@@ -104,7 +104,7 @@
     displayItemList.preInitialize();
     displayItemList.initialize();
 
-    var dbg = new tv.e.cc.DisplayItemDebugger();
+    var dbg = new tr.e.cc.DisplayItemDebugger();
     this.addHTMLOutput(dbg);
     dbg.displayItemList = displayItemList;
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list.html b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list.html
index 58888b3..3aa0082 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list.html
@@ -6,34 +6,34 @@
 -->
 
 <link rel="import" href="/extras/chrome/cc/picture.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.cc', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   function DisplayItemList(skp64, layerRect) {
-    tv.e.cc.Picture.apply(this, arguments);
+    tr.e.cc.Picture.apply(this, arguments);
   }
 
   DisplayItemList.prototype = {
-    __proto__: tv.e.cc.Picture.prototype
+    __proto__: tr.e.cc.Picture.prototype
   };
 
   /**
    * @constructor
    */
   function DisplayItemListSnapshot() {
-    tv.e.cc.PictureSnapshot.apply(this, arguments);
+    tr.e.cc.PictureSnapshot.apply(this, arguments);
   }
 
   DisplayItemListSnapshot.prototype = {
-    __proto__: tv.e.cc.PictureSnapshot.prototype,
+    __proto__: tr.e.cc.PictureSnapshot.prototype,
 
     initialize: function() {
-      tv.e.cc.PictureSnapshot.prototype.initialize.call(this);
+      tr.e.cc.PictureSnapshot.prototype.initialize.call(this);
       this.displayItems_ = this.args.params.items;
     },
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list_test.html
index bc22d78..8329931 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_list_test.html
@@ -8,28 +8,28 @@
 <link rel="import" href="/extras/chrome/cc/cc.html">
 <link rel="import" href="/extras/chrome/cc/display_item_list.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::DisplayItemList')[0];
     var snapshot = instance.snapshots[0];
 
-    assert.instanceOf(snapshot, tv.e.cc.DisplayItemListSnapshot);
+    assert.instanceOf(snapshot, tr.e.cc.DisplayItemListSnapshot);
     instance.wasDeleted(150);
   });
 
   test('getItems', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::DisplayItemList')[0];
     var snapshot = instance.snapshots[0];
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_view.html
index 0dd532d..e61cee5 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/display_item_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/display_item_view.html
@@ -11,26 +11,26 @@
 <link rel="import" href="/extras/chrome/cc/display_item_debugger.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
 <link rel="import" href="/core/analysis/object_snapshot_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /*
    * Displays a display item snapshot in a human readable form.
    * @constructor
    */
-  var DisplayItemSnapshotView = tv.b.ui.define(
+  var DisplayItemSnapshotView = tr.b.ui.define(
       'display-item-snapshot-view',
-      tv.c.analysis.ObjectSnapshotView);
+      tr.c.analysis.ObjectSnapshotView);
 
   DisplayItemSnapshotView.prototype = {
-    __proto__: tv.c.analysis.ObjectSnapshotView.prototype,
+    __proto__: tr.c.analysis.ObjectSnapshotView.prototype,
 
     decorate: function() {
       this.classList.add('display-item-view');
-      this.displayItemDebugger_ = new tv.e.cc.DisplayItemDebugger();
+      this.displayItemDebugger_ = new tr.e.cc.DisplayItemDebugger();
       this.appendChild(this.displayItemDebugger_);
     },
 
@@ -40,7 +40,7 @@
     }
   };
 
-  tv.c.analysis.ObjectSnapshotView.register(
+  tr.c.analysis.ObjectSnapshotView.register(
       DisplayItemSnapshotView,
       {
         typeNames: ['cc::DisplayItemList'],
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice.html b/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice.html
index c91cdb2..23f0349 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice.html
@@ -4,13 +4,13 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/core/trace_model/async_slice.html">
+<link rel="import" href="/model/async_slice.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
-  var AsyncSlice = tv.c.trace_model.AsyncSlice;
+tr.exportTo('tr.e.cc', function() {
+  var AsyncSlice = tr.model.AsyncSlice;
 
 
   var UI_COMP_NAME = 'INPUT_EVENT_LATENCY_UI_COMPONENT';
@@ -18,14 +18,37 @@
   var BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT';
   var END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT';
 
-
   function InputLatencyAsyncSlice() {
     AsyncSlice.apply(this, arguments);
+    this.associatedEvents_ = undefined;
   }
 
   InputLatencyAsyncSlice.prototype = {
     __proto__: AsyncSlice.prototype,
 
+    get associatedEvents() {
+      if (this.associatedEvents_ !== undefined)
+        return this.associatedEvents_;
+
+      this.associatedEvents_ = [];
+      var modelIndices = this.startThread.parent.model.modelIndices;
+      var matchedFlowEvents = modelIndices.getFlowEventsWithId(this.id);
+
+      var eventGUIDs = {};
+      matchedFlowEvents.forEach(function(flowEvent) {
+        this.associatedEvents_.push(flowEvent);
+        if (flowEvent.startSlice && !eventGUIDs[flowEvent.startSlice.guid]) {
+          this.associatedEvents_.push(flowEvent.startSlice);
+          eventGUIDs[flowEvent.startSlice.guid] = 1;
+        }
+        if (flowEvent.startSlice && !eventGUIDs[flowEvent.endSlice.guid]) {
+          this.associatedEvents_.push(flowEvent.endSlice);
+          eventGUIDs[flowEvent.endSlice.guid] = 1;
+        }
+      }, this);
+
+      return this.associatedEvents_;
+    },
 
     get inputLatency() {
       if (!('data' in this.args))
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice_test.html
index 9a97bf6..2518a98 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/input_latency_async_slice_test.html
@@ -7,13 +7,17 @@
 
 <link rel="import" href="/extras/chrome/cc/input_latency_async_slice.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/model_indices.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newAsyncSliceEx = tv.c.test_utils.newAsyncSliceEx;
+tr.b.unittest.testSuite(function() {
+  var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
+  var newFlowEventEx = tr.c.test_utils.newFlowEventEx;
+  var newModel = tr.c.test_utils.newModel;
 
   test('matchByType_oldStyle', function() {
     var sOuter = newAsyncSliceEx({
@@ -42,8 +46,8 @@
       }
     });
     sOuter.subSlices.push(sInner);
-    assert.isTrue(sOuter instanceof tv.e.cc.InputLatencyAsyncSlice);
-    assert.isTrue(sInner instanceof tv.e.cc.InputLatencyAsyncSlice);
+    assert.isTrue(sOuter instanceof tr.e.cc.InputLatencyAsyncSlice);
+    assert.isTrue(sInner instanceof tr.e.cc.InputLatencyAsyncSlice);
     assert.equal(sOuter.inputLatency, 10);
   });
 
@@ -63,7 +67,7 @@
       }
     });
 
-    assert.isTrue(sInfo instanceof tv.e.cc.InputLatencyAsyncSlice);
+    assert.isTrue(sInfo instanceof tr.e.cc.InputLatencyAsyncSlice);
     assert.equal(sInfo.inputLatency, 10);
   });
 
@@ -84,9 +88,81 @@
       }
     });
 
-    assert.isTrue(sInfo instanceof tv.e.cc.InputLatencyAsyncSlice);
+    assert.isTrue(sInfo instanceof tr.e.cc.InputLatencyAsyncSlice);
     assert.equal(sInfo.inputLatency, 10);
   });
 
+  test('testGetAssociatedEvents', function() {
+    var m = newModel(function(m) {
+
+      var p = m.getOrCreateProcess(1);
+      var t = p.getOrCreateThread(1);
+
+      var s0 = newSliceEx({
+        title: 'a',
+        start: 0.0,
+        duration: 0.5
+      });
+
+      var s1 = newSliceEx({
+        title: 'b',
+        start: 0.5,
+        duration: 0.5
+      });
+
+      var s2 = newSliceEx({
+        title: 'c',
+        start: 1.0,
+        duration: 0.5
+      });
+
+      var f1 = newFlowEventEx({
+        'title': 'test1',
+        start: 0,
+        end: 10,
+        startSlice: s0,
+        endSlice: s1,
+        id: '0x100'
+      });
+
+      var f2 = newFlowEventEx({
+        'title': 'test2',
+        start: 20,
+        end: 30,
+        startSlice: s1,
+        endSlice: s2,
+        id: '0x100'
+      });
+
+      m.flowEvents.push(f1);
+      m.flowEvents.push(f2);
+
+      m.as0 = newAsyncSliceEx({
+        title: 'InputLatency::TestShouldReturnEmpty',
+        cat: 'benchmark,latencyInfo',
+        start: 2,
+        end: 10,
+        id: '0x101',
+        isTopLevel: true,
+        startThread: t
+      });
+
+      m.as1 = newAsyncSliceEx({
+        title: 'InputLatency::TestShouldReturnTwoElements',
+        cat: 'benchmark,latencyInfo',
+        start: 2,
+        end: 10,
+        id: '0x100',
+        isTopLevel: true,
+        startThread: t
+      });
+
+    });
+
+    assert.equal(m.as0.associatedEvents.length, 0);
+    assert.equal(m.as1.associatedEvents.length, 5);
+    assert.equal(m.as1.associatedEvents[0].id, '0x100');
+  });
+
 });
 </script>
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_impl.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_impl.html
index 5613fff..28ada3e 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_impl.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_impl.html
@@ -9,14 +9,14 @@
 <link rel="import" href="/extras/chrome/cc/region.html">
 <link rel="import" href="/extras/chrome/cc/tile_coverage_rect.html">
 <link rel="import" href="/base/rect.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
-  var constants = tv.e.cc.constants;
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.cc', function() {
+  var constants = tr.e.cc.constants;
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * @constructor
@@ -29,7 +29,7 @@
     __proto__: ObjectSnapshot.prototype,
 
     preInitialize: function() {
-      tv.e.cc.preInitializeObject(this);
+      tr.e.cc.preInitializeObject(this);
 
       this.layerTreeImpl_ = undefined;
       this.parentLayer = undefined;
@@ -37,16 +37,16 @@
 
     initialize: function() {
       // Defaults.
-      this.invalidation = new tv.e.cc.Region();
-      this.annotatedInvalidation = new tv.e.cc.Region();
-      this.unrecordedRegion = new tv.e.cc.Region();
+      this.invalidation = new tr.e.cc.Region();
+      this.annotatedInvalidation = new tr.e.cc.Region();
+      this.unrecordedRegion = new tr.e.cc.Region();
       this.pictures = [];
 
       // Import & validate this.args
-      tv.e.cc.moveRequiredFieldsFromArgsToToplevel(
+      tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
           this, ['layerId', 'children',
                  'layerQuad']);
-      tv.e.cc.moveOptionalFieldsFromArgsToToplevel(
+      tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
           this, ['maskLayer', 'replicaLayer',
                  'idealContentsScale', 'geometryContentsScale',
                  'layoutRects', 'usingGpuRasterization']);
@@ -55,13 +55,13 @@
       this.gpuMemoryUsageInBytes = this.args.gpuMemoryUsage;
 
       // Leave bounds in both places.
-      this.bounds = tv.b.Rect.fromXYWH(
+      this.bounds = tr.b.Rect.fromXYWH(
           0, 0,
           this.args.bounds.width, this.args.bounds.height);
 
       if (this.args.animationBounds) {
         // AnimationBounds[2] and [5] are the Z-component of the box.
-        this.animationBoundsRect = tv.b.Rect.fromXYWH(
+        this.animationBoundsRect = tr.b.Rect.fromXYWH(
             this.args.animationBounds[0], this.args.animationBounds[1],
             this.args.animationBounds[3], this.args.animationBounds[4]);
       }
@@ -74,12 +74,14 @@
         this.replicaLayer.parentLayer = this;
       if (!this.geometryContentsScale)
         this.geometryContentsScale = 1.0;
+      if (!this.idealContentsScale)
+        this.idealContentsScale = 1.0;
 
-      this.touchEventHandlerRegion = tv.e.cc.Region.fromArrayOrUndefined(
+      this.touchEventHandlerRegion = tr.e.cc.Region.fromArrayOrUndefined(
           this.args.touchEventHandlerRegion);
-      this.wheelEventHandlerRegion = tv.e.cc.Region.fromArrayOrUndefined(
+      this.wheelEventHandlerRegion = tr.e.cc.Region.fromArrayOrUndefined(
           this.args.wheelEventHandlerRegion);
-      this.nonFastScrollableRegion = tv.e.cc.Region.fromArrayOrUndefined(
+      this.nonFastScrollableRegion = tr.e.cc.Region.fromArrayOrUndefined(
           this.args.nonFastScrollableRegion);
     },
 
@@ -123,11 +125,11 @@
       LayerImplSnapshot.prototype.initialize.call(this);
 
       if (this.args.invalidation) {
-        this.invalidation = tv.e.cc.Region.fromArray(this.args.invalidation);
+        this.invalidation = tr.e.cc.Region.fromArray(this.args.invalidation);
         delete this.args.invalidation;
       }
       if (this.args.annotatedInvalidationRects) {
-        this.annotatedInvalidation = new tv.e.cc.Region();
+        this.annotatedInvalidation = new tr.e.cc.Region();
         for (var i = 0; i < this.args.annotatedInvalidationRects.length; ++i) {
           var annotatedRect = this.args.annotatedInvalidationRects[i];
           var rect = annotatedRect.geometryRect;
@@ -137,7 +139,7 @@
         delete this.args.annotatedInvalidationRects;
       }
       if (this.args.unrecordedRegion) {
-        this.unrecordedRegion = tv.e.cc.Region.fromArray(
+        this.unrecordedRegion = tr.e.cc.Region.fromArray(
             this.args.unrecordedRegion);
         delete this.args.unrecordedRegion;
       }
@@ -153,9 +155,10 @@
       this.tileCoverageRects = [];
       if (this.args.coverageTiles) {
         for (var i = 0; i < this.args.coverageTiles.length; ++i) {
-          var rect = this.args.coverageTiles[i].geometryRect;
+          var rect = this.args.coverageTiles[i].geometryRect.scale(
+              this.idealContentsScale);
           var tile = this.args.coverageTiles[i].tile;
-          this.tileCoverageRects.push(new tv.e.cc.TileCoverageRect(rect, tile));
+          this.tileCoverageRects.push(new tr.e.cc.TileCoverageRect(rect, tile));
         }
         delete this.args.coverageTiles;
       }
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.css b/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.css
index 398205f..22c9718 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.css
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.css
@@ -31,13 +31,13 @@
   overflow: auto;
 }
 
-* /deep/ layer-picker > tv-c-analysis-generic-object-view {
+* /deep/ layer-picker > tr-c-a-generic-object-view {
   -webkit-flex: 0 0 auto;
   height: 200px;
   overflow: auto;
 }
 
-* /deep/ layer-picker > tv-c-analysis-generic-object-view * {
+* /deep/ layer-picker > tr-c-a-generic-object-view * {
   -webkit-user-select: text !important;
   cursor: text;
 }
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.html
index c75a126..715e042 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_picker.html
@@ -12,7 +12,7 @@
 <link rel="import" href="/extras/chrome/cc/selection.html">
 <link rel="import" href="/extras/chrome/cc/util.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/model/event.html">
 <link rel="import" href="/base/ui/drag_handle.html">
 <link rel="import" href="/base/ui/list_view.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
@@ -20,16 +20,16 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
-  var constants = tv.e.cc.constants;
-  var bytesToRoundedMegabytes = tv.e.cc.bytesToRoundedMegabytes;
+tr.exportTo('tr.e.cc', function() {
+  var constants = tr.e.cc.constants;
+  var bytesToRoundedMegabytes = tr.e.cc.bytesToRoundedMegabytes;
   var RENDER_PASS_QUADS =
       Math.max(constants.ACTIVE_TREE, constants.PENDING_TREE) + 1;
 
   /**
    * @constructor
    */
-  var LayerPicker = tv.b.ui.define('layer-picker');
+  var LayerPicker = tr.b.ui.define('layer-picker');
 
   LayerPicker.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -40,7 +40,7 @@
       this.renderPassQuads_ = false;
 
 
-      this.itemList_ = new tv.b.ui.ListView();
+      this.itemList_ = new tr.b.ui.ListView();
       this.appendChild(this.controls_);
 
       this.appendChild(this.itemList_);
@@ -48,7 +48,7 @@
       this.itemList_.addEventListener(
           'selection-changed', this.onItemSelectionChanged_.bind(this));
 
-      this.controls_.appendChild(tv.b.ui.createSelector(
+      this.controls_.appendChild(tr.b.ui.createSelector(
           this, 'whichTree',
           'layerPicker.whichTree', constants.ACTIVE_TREE,
           [{label: 'Active tree', value: constants.ACTIVE_TREE},
@@ -56,7 +56,7 @@
            {label: 'Render pass quads', value: RENDER_PASS_QUADS}]));
 
       this.showPureTransformLayers_ = false;
-      var showPureTransformLayers = tv.b.ui.createCheckBox(
+      var showPureTransformLayers = tr.b.ui.createCheckBox(
           this, 'showPureTransformLayers',
           'layerPicker.showPureTransformLayers', false,
           'Transform layers');
@@ -83,7 +83,7 @@
       this.whichTree_ = whichTree;
       this.renderPassQuads_ = (whichTree == RENDER_PASS_QUADS);
       this.updateContents_();
-      tv.b.dispatchSimpleEvent(this, 'selection-change', false);
+      tr.b.dispatchSimpleEvent(this, 'selection-change', false);
     },
 
     get layerTreeImpl() {
@@ -197,7 +197,7 @@
         var id = renderPassInfo.id;
 
         var item = this.createElementWithDepth_(renderPassInfo.depth);
-        var labelEl = item.appendChild(tv.b.ui.createSpan());
+        var labelEl = item.appendChild(tr.b.ui.createSpan());
 
         labelEl.textContent = renderPassInfo.name + ' ' + id;
         item.renderPass = renderPass;
@@ -206,7 +206,7 @@
 
         if (id == selectedRenderPassId) {
           renderPass.selectionState =
-              tv.c.trace_model.SelectionState.SELECTED;
+              tr.model.SelectionState.SELECTED;
         }
       }, this);
     },
@@ -226,11 +226,11 @@
           var id = layer.layerId;
 
           var item = this.createElementWithDepth_(layerInfo.depth);
-          var labelEl = item.appendChild(tv.b.ui.createSpan());
+          var labelEl = item.appendChild(tr.b.ui.createSpan());
 
           labelEl.textContent = layerInfo.name + ' ' + id;
 
-          var notesEl = item.appendChild(tv.b.ui.createSpan());
+          var notesEl = item.appendChild(tr.b.ui.createSpan());
           if (layerInfo.isMaskLayer)
             notesEl.textContent += '(mask)';
           if (layerInfo.isReplicaLayer)
@@ -246,7 +246,7 @@
           this.itemList_.appendChild(item);
 
           if (layer.layerId == selectedLayerId) {
-            layer.selectionState = tv.c.trace_model.SelectionState.SELECTED;
+            layer.selectionState = tr.model.SelectionState.SELECTED;
             item.selected = true;
           }
         }, this);
@@ -258,7 +258,7 @@
     createElementWithDepth_: function(depth) {
       var item = document.createElement('div');
 
-      var indentEl = item.appendChild(tv.b.ui.createSpan());
+      var indentEl = item.appendChild(tr.b.ui.createSpan());
       indentEl.style.whiteSpace = 'pre';
       for (var i = 0; i < depth; i++)
         indentEl.textContent = indentEl.textContent + ' ';
@@ -272,7 +272,7 @@
         this.onRenderPassSelected_(e);
       else
         this.onLayerSelected_(e);
-      tv.b.dispatchSimpleEvent(this, 'selection-change', false);
+      tr.b.dispatchSimpleEvent(this, 'selection-change', false);
     },
 
     onRenderPassSelected_: function(e) {
@@ -285,7 +285,7 @@
       }
 
       if (selectedRenderPass) {
-        this.selection_ = new tv.e.cc.RenderPassSelection(
+        this.selection_ = new tr.e.cc.RenderPassSelection(
             selectedRenderPass, selectedRenderPassId);
       } else {
         this.selection_ = undefined;
@@ -298,7 +298,7 @@
         selectedLayer = this.itemList_.selectedElement.layer;
 
       if (selectedLayer)
-        this.selection_ = new tv.e.cc.LayerSelection(selectedLayer);
+        this.selection_ = new tr.e.cc.LayerSelection(selectedLayer);
       else
         this.selection_ = undefined;
     },
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl.html
index d424135..43c6a87 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl.html
@@ -9,7 +9,7 @@
 <link rel="import" href="/extras/chrome/cc/layer_tree_impl.html">
 <link rel="import" href="/extras/chrome/cc/util.html">
 <link rel="import" href="/base/bbox2.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
@@ -17,11 +17,11 @@
 /**
  * @fileoverview Provides the LayerTreeHostImpl model-level objects.
  */
-tv.exportTo('tv.e.cc', function() {
-  var constants = tv.e.cc.constants;
+tr.exportTo('tr.e.cc', function() {
+  var constants = tr.e.cc.constants;
 
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
-  var ObjectInstance = tv.c.trace_model.ObjectInstance;
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
+  var ObjectInstance = tr.model.ObjectInstance;
 
   /**
    * @constructor
@@ -34,14 +34,14 @@
     __proto__: ObjectSnapshot.prototype,
 
     preInitialize: function() {
-      tv.e.cc.preInitializeObject(this);
+      tr.e.cc.preInitializeObject(this);
     },
 
     initialize: function() {
-      tv.e.cc.moveRequiredFieldsFromArgsToToplevel(
+      tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
           this, ['deviceViewportSize',
             'activeTree']);
-      tv.e.cc.moveOptionalFieldsFromArgsToToplevel(
+      tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
           this, ['pendingTree']);
 
       // Move active_tiles into this.tiles. If that doesn't exist then, then as
@@ -156,14 +156,14 @@
         var tileHistory = this.allTileHistories_[tileID];
         scales[tileHistory.contentsScale] = true;
       }
-      this.allContentsScales_ = tv.b.dictionaryKeys(scales);
+      this.allContentsScales_ = tr.b.dictionaryKeys(scales);
       return this.allContentsScales_;
     },
 
     get allLayersBBox() {
       if (this.allLayersBBox_)
         return this.allLayersBBox_;
-      var bbox = new tv.b.BBox2();
+      var bbox = new tr.b.BBox2();
       function handleTree(tree) {
         tree.renderSurfaceLayerList.forEach(function(layer) {
           bbox.addQuad(layer.layerQuad);
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_test.html
index ab50c4f..714ec60 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_test.html
@@ -7,22 +7,22 @@
 
 <link rel="import" href="/extras/chrome/cc/layer_tree_host_impl.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
     var snapshot = instance.snapshots[0];
 
-    assert.instanceOf(snapshot, tv.e.cc.LayerTreeHostImplSnapshot);
+    assert.instanceOf(snapshot, tr.e.cc.LayerTreeHostImplSnapshot);
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.html
index cfadbf9..2526d3c 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view.html
@@ -17,33 +17,33 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /*
    * Displays a LayerTreeHostImpl snapshot in a human readable form.
    * @constructor
    */
-  var LayerTreeHostImplSnapshotView = tv.b.ui.define(
+  var LayerTreeHostImplSnapshotView = tr.b.ui.define(
       'layer-tree-host-impl-snapshot-view',
-      tv.c.analysis.ObjectSnapshotView);
+      tr.c.analysis.ObjectSnapshotView);
 
   LayerTreeHostImplSnapshotView.prototype = {
-    __proto__: tv.c.analysis.ObjectSnapshotView.prototype,
+    __proto__: tr.c.analysis.ObjectSnapshotView.prototype,
 
     decorate: function() {
       this.classList.add('lthi-s-view');
 
       this.selection_ = undefined;
 
-      this.layerPicker_ = new tv.e.cc.LayerPicker();
+      this.layerPicker_ = new tr.e.cc.LayerPicker();
       this.layerPicker_.addEventListener(
           'selection-change',
           this.onLayerPickerSelectionChanged_.bind(this));
 
-      this.layerView_ = new tv.e.cc.LayerView();
+      this.layerView_ = new tr.e.cc.LayerView();
       this.layerView_.addEventListener(
           'selection-change',
           this.onLayerViewSelectionChanged_.bind(this));
-      this.dragHandle_ = new tv.b.ui.DragHandle();
+      this.dragHandle_ = new tr.b.ui.DragHandle();
       this.dragHandle_.horizontal = false;
       this.dragHandle_.target = this.layerView_;
 
@@ -89,7 +89,7 @@
       this.selection_ = selection;
       this.layerPicker_.selection = selection;
       this.layerView_.selection = selection;
-      tv.b.dispatchSimpleEvent(this, 'cc-selection-change');
+      tr.b.dispatchSimpleEvent(this, 'cc-selection-change');
     },
 
     onLayerPickerSelectionChanged_: function() {
@@ -98,13 +98,13 @@
       this.layerView_.layerTreeImpl = this.layerPicker_.layerTreeImpl;
       this.layerView_.isRenderPassQuads = this.layerPicker_.isRenderPassQuads;
       this.layerView_.regenerateContent();
-      tv.b.dispatchSimpleEvent(this, 'cc-selection-change');
+      tr.b.dispatchSimpleEvent(this, 'cc-selection-change');
     },
 
     onLayerViewSelectionChanged_: function() {
       this.selection_ = this.layerView_.selection;
       this.layerPicker_.selection = this.selection;
-      tv.b.dispatchSimpleEvent(this, 'cc-selection-change');
+      tr.b.dispatchSimpleEvent(this, 'cc-selection-change');
     },
 
     get extraHighlightsByLayerId() {
@@ -116,7 +116,7 @@
     }
   };
 
-  tv.c.analysis.ObjectSnapshotView.register(
+  tr.c.analysis.ObjectSnapshotView.register(
       LayerTreeHostImplSnapshotView, {typeName: 'cc::LayerTreeHostImpl'});
 
   return {
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view_test.html
index 3546a8e..54311f5 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_host_impl_view_test.html
@@ -8,23 +8,23 @@
 <link rel="import" href="/extras/chrome/cc/layer_tree_host_impl.html">
 <link rel="import" href="/extras/chrome/cc/layer_tree_host_impl_view.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/chrome/cc/raster_task.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
     var snapshot = instance.snapshots[0];
 
-    var view = new tv.e.cc.LayerTreeHostImplSnapshotView();
+    var view = new tr.e.cc.LayerTreeHostImplSnapshotView();
     view.style.width = '900px';
     view.style.height = '400px';
     view.objectSnapshot = snapshot;
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_impl.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_impl.html
index 8b21b42..08d074e 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_impl.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_impl.html
@@ -8,15 +8,15 @@
 <link rel="import" href="/extras/chrome/chrome_model_helper.html">
 <link rel="import" href="/extras/chrome/cc/constants.html">
 <link rel="import" href="/extras/chrome/cc/layer_impl.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
 
-  var constants = tv.e.cc.constants;
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+  var constants = tr.e.cc.constants;
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * @constructor
@@ -29,14 +29,14 @@
     __proto__: ObjectSnapshot.prototype,
 
     preInitialize: function() {
-      tv.e.cc.preInitializeObject(this);
+      tr.e.cc.preInitializeObject(this);
       this.layerTreeHostImpl = undefined;
       this.whichTree = undefined;
       this.sourceFrameNumber = undefined;
     },
 
     initialize: function() {
-      tv.e.cc.moveRequiredFieldsFromArgsToToplevel(
+      tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
           this, ['rootLayer',
             'renderSurfaceLayerList']);
       if (this.args.sourceFrameNumber)
@@ -48,19 +48,19 @@
         this.tracedInputLatencies = [];
 
         var ownProcess = this.objectInstance.parent;
-        var traceModel = ownProcess.model;
-        if (tv.e.audits.ChromeModelHelper.supportsModel(traceModel))
-          this._initializeTracedInputLatencies(traceModel);
+        var model = ownProcess.model;
+        if (tr.e.audits.ChromeModelHelper.supportsModel(model))
+          this._initializeTracedInputLatencies(model);
       }
     },
 
-    _initializeTracedInputLatencies: function(traceModel) {
-      var modelHelper = new tv.e.audits.ChromeModelHelper(traceModel);
-      if (!modelHelper.browser)
+    _initializeTracedInputLatencies: function(model) {
+      var modelHelper = new tr.e.audits.ChromeModelHelper(model);
+      if (!modelHelper.browserHelper)
         return;
 
-      var latencyEvents = modelHelper.browser.getLatencyEventsInRange(
-          traceModel.bounds);
+      var latencyEvents = modelHelper.browserHelper.getLatencyEventsInRange(
+          model.bounds);
 
       // Convert all ids to InputLatency Async objects.
       latencyEvents.forEach(function(event) {
@@ -75,7 +75,7 @@
     },
 
     get hasSourceFrameBeenDrawnBefore() {
-      if (this.whichTree == tv.e.cc.constants.PENDING_TREE)
+      if (this.whichTree == tr.e.cc.constants.PENDING_TREE)
         return false;
 
       // Old chrome's don't produce sourceFrameNumber.
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view.html
index eb7e879..6e3c617 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view.html
@@ -70,7 +70,7 @@
  * @fileoverview Graphical view of  LayerTreeImpl, with controls for
  * type of layer content shown and info bar for content-loading warnings.
  */
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
 
   var THIS_DOC = document.currentScript.ownerDocument;
   var TILE_HEATMAP_TYPE = {};
@@ -83,13 +83,13 @@
             {label: 'Coverage Rects', value: 'coverage'}];
   }
 
-  var bytesToRoundedMegabytes = tv.e.cc.bytesToRoundedMegabytes;
+  var bytesToRoundedMegabytes = tr.e.cc.bytesToRoundedMegabytes;
 
 
   /**
    * @constructor
    */
-  var LayerTreeQuadStackView = tv.b.ui.define('layer-tree-quad-stack-view');
+  var LayerTreeQuadStackView = tr.b.ui.define('layer-tree-quad-stack-view');
 
   LayerTreeQuadStackView.prototype = {
     __proto__: HTMLDivElement.prototype,
@@ -99,40 +99,40 @@
       this.pictureAsImageData_ = {}; // Maps picture.guid to PictureAsImageData.
       this.messages_ = [];
       this.controls_ = document.createElement('top-controls');
-      this.infoBar_ = document.createElement('tv-b-ui-info-bar');
-      this.quadStackView_ = new tv.b.ui.QuadStackView();
+      this.infoBar_ = document.createElement('tr-b-ui-info-bar');
+      this.quadStackView_ = new tr.b.ui.QuadStackView();
       this.quadStackView_.addEventListener(
           'selectionchange', this.onQuadStackViewSelectionChange_.bind(this));
       this.extraHighlightsByLayerId_ = undefined;
       this.inputEventImageData_ = undefined;
 
-      var m = tv.b.ui.MOUSE_SELECTOR_MODE;
+      var m = tr.b.ui.MOUSE_SELECTOR_MODE;
       var mms = this.quadStackView_.mouseModeSelector;
-      mms.settingsKey = 'tv.e.cc.layerTreeQuadStackView.mouseModeSelector';
+      mms.settingsKey = 'tr.e.cc.layerTreeQuadStackView.mouseModeSelector';
       mms.setKeyCodeForMode(m.SELECTION, 'Z'.charCodeAt(0));
       mms.setKeyCodeForMode(m.PANSCAN, 'X'.charCodeAt(0));
       mms.setKeyCodeForMode(m.ZOOM, 'C'.charCodeAt(0));
       mms.setKeyCodeForMode(m.ROTATE, 'V'.charCodeAt(0));
 
-      var node = tv.b.instantiateTemplate(
+      var node = tr.b.instantiateTemplate(
           '#layer-tree-quad-stack-view-template', THIS_DOC);
       this.appendChild(node);
       this.appendChild(this.controls_);
       this.appendChild(this.infoBar_);
       this.appendChild(this.quadStackView_);
 
-      this.tileRectsSelector_ = tv.b.ui.createSelector(
+      this.tileRectsSelector_ = tr.b.ui.createSelector(
           this, 'howToShowTiles',
           'layerView.howToShowTiles', 'none',
           createTileRectsSelectorBaseOptions());
       this.controls_.appendChild(this.tileRectsSelector_);
 
-      var tileHeatmapText = tv.b.ui.createSpan({
+      var tileHeatmapText = tr.b.ui.createSpan({
         textContent: 'Tile heatmap:'
       });
       this.controls_.appendChild(tileHeatmapText);
 
-      var tileHeatmapSelector = tv.b.ui.createSelector(
+      var tileHeatmapSelector = tr.b.ui.createSelector(
           this, 'tileHeatmapType',
           'layerView.tileHeatmapType', TILE_HEATMAP_TYPE.NONE,
           [{label: 'None',
@@ -144,7 +144,7 @@
           ]);
       this.controls_.appendChild(tileHeatmapSelector);
 
-      var showOtherLayersCheckbox = tv.b.ui.createCheckBox(
+      var showOtherLayersCheckbox = tr.b.ui.createCheckBox(
           this, 'showOtherLayers',
           'layerView.showOtherLayers', true,
           'Other layers/passes');
@@ -152,7 +152,7 @@
           'When checked, show all layers, selected or not.';
       this.controls_.appendChild(showOtherLayersCheckbox);
 
-      var showInvalidationsCheckbox = tv.b.ui.createCheckBox(
+      var showInvalidationsCheckbox = tr.b.ui.createCheckBox(
           this, 'showInvalidations',
           'layerView.showInvalidations', true,
           'Invalidations');
@@ -160,7 +160,7 @@
           'When checked, compositing invalidations are highlighted in red';
       this.controls_.appendChild(showInvalidationsCheckbox);
 
-      var showUnrecordedRegionCheckbox = tv.b.ui.createCheckBox(
+      var showUnrecordedRegionCheckbox = tr.b.ui.createCheckBox(
           this, 'showUnrecordedRegion',
           'layerView.showUnrecordedRegion', true,
           'Unrecorded area');
@@ -168,7 +168,7 @@
           'When checked, unrecorded areas are highlighted in yellow';
       this.controls_.appendChild(showUnrecordedRegionCheckbox);
 
-      var showBottlenecksCheckbox = tv.b.ui.createCheckBox(
+      var showBottlenecksCheckbox = tr.b.ui.createCheckBox(
           this, 'showBottlenecks',
           'layerView.showBottlenecks', true,
           'Bottlenecks');
@@ -176,7 +176,7 @@
           'When checked, scroll bottlenecks are highlighted';
       this.controls_.appendChild(showBottlenecksCheckbox);
 
-      var showLayoutRectsCheckbox = tv.b.ui.createCheckBox(
+      var showLayoutRectsCheckbox = tr.b.ui.createCheckBox(
           this, 'showLayoutRects',
           'layerView.showLayoutRects', false,
           'Layout rects');
@@ -184,7 +184,7 @@
           'When checked, shows rects for regions where layout happened';
       this.controls_.appendChild(showLayoutRectsCheckbox);
 
-      var showContentsCheckbox = tv.b.ui.createCheckBox(
+      var showContentsCheckbox = tr.b.ui.createCheckBox(
           this, 'showContents',
           'layerView.showContents', true,
           'Contents');
@@ -192,7 +192,7 @@
           'When checked, show the rendered contents inside the layer outlines';
       this.controls_.appendChild(showContentsCheckbox);
 
-      var showAnimationBoundsCheckbox = tv.b.ui.createCheckBox(
+      var showAnimationBoundsCheckbox = tr.b.ui.createCheckBox(
           this, 'showAnimationBounds',
           'layerView.showAnimationBounds', false,
           'Animation Bounds');
@@ -200,7 +200,7 @@
           ' a layer showing the extent of its animation.';
       this.controls_.appendChild(showAnimationBoundsCheckbox);
 
-      var showInputEventsCheckbox = tv.b.ui.createCheckBox(
+      var showInputEventsCheckbox = tr.b.ui.createCheckBox(
           this, 'showInputEvents',
           'layerView.showInputEvents', true,
           'Input events');
@@ -350,7 +350,7 @@
       if (this.selection === selection)
         return;
       this.selection_ = selection;
-      tv.b.dispatchSimpleEvent(this, 'selection-change');
+      tr.b.dispatchSimpleEvent(this, 'selection-change');
       this.updateContents_();
     },
 
@@ -401,7 +401,7 @@
       if (this.updateContentsPending_)
         return;
       this.updateContentsPending_ = true;
-      tv.b.requestAnimationFrameInThisFrameIfPossible(
+      tr.b.requestAnimationFrameInThisFrameIfPossible(
           this.updateContents_, this);
     },
 
@@ -419,7 +419,7 @@
 
       var lthi = this.layerTreeImpl_.layerTreeHostImpl;
       var lthiInstance = lthi.objectInstance;
-      var worldViewportRect = tv.b.Rect.fromXYWH(
+      var worldViewportRect = tr.b.Rect.fromXYWH(
           0, 0,
           lthi.deviceViewportSize.width, lthi.deviceViewportSize.height);
       this.quadStackView_.deviceRect = worldViewportRect;
@@ -475,7 +475,7 @@
         // event so that we show some global state.
         var thread = lthi.snapshottedOnThread;
         var didManageTilesSlices = thread.sliceGroup.slices.filter(function(s) {
-          if (s.category !== 'tv.e.cc')
+          if (s.category !== 'tr.e.cc')
             return false;
           if (s.title !== 'DidManage')
             return false;
@@ -525,7 +525,7 @@
       }
 
       // Then create a new selector and replace the old one.
-      var new_selector = tv.b.ui.createSelector(
+      var new_selector = tr.b.ui.createSelector(
           this, 'howToShowTiles',
           'layerView.howToShowTiles', 'none',
           data);
@@ -564,7 +564,7 @@
             if (!pictureAsImageData) {
               hasPendingRasterizeImage = true;
               this.pictureAsImageData_[picture.guid] =
-                  tv.e.cc.PictureAsImageData.Pending(this);
+                  tr.e.cc.PictureAsImageData.Pending(this);
               picture.rasterize(
                   {stopIndex: undefined},
                   function(pictureImageData) {
@@ -683,13 +683,13 @@
         return;
 
       var rect = layer.animationBoundsRect;
-      var abq = tv.b.Quad.fromRect(rect);
+      var abq = tr.b.Quad.fromRect(rect);
 
       abq.backgroundColor = 'rgba(164,191,48,0.5)';
       abq.borderColor = 'rgba(205,255,0,0.75)';
       abq.borderWidth = 3.0;
       abq.stackingGroupId = layerQuad.stackingGroupId;
-      abq.selectionToSetIfClicked = new tv.e.cc.AnimationRectSelection(
+      abq.selectionToSetIfClicked = new tr.e.cc.AnimationRectSelection(
           layer, rect);
       quads.push(abq);
     },
@@ -708,7 +708,7 @@
             iq.backgroundColor = 'rgba(0, 255, 128, 0.1)';
         iq.borderColor = 'rgba(0, 255, 0, 1)';
         iq.stackingGroupId = layerQuad.stackingGroupId;
-        iq.selectionToSetIfClicked = new tv.e.cc.LayerRectSelection(
+        iq.selectionToSetIfClicked = new tr.e.cc.LayerRectSelection(
             layer, 'Invalidation rect (' + rect.reason + ')', rect, rect);
         quads.push(iq);
       }
@@ -723,7 +723,7 @@
           iq.backgroundColor = 'rgba(0, 255, 0, 0.1)';
           iq.borderColor = 'rgba(0, 255, 0, 1)';
           iq.stackingGroupId = layerQuad.stackingGroupId;
-          iq.selectionToSetIfClicked = new tv.e.cc.LayerRectSelection(
+          iq.selectionToSetIfClicked = new tr.e.cc.LayerRectSelection(
               layer, 'Invalidation rect', rect, rect);
           quads.push(iq);
         }
@@ -739,7 +739,7 @@
         iq.backgroundColor = 'rgba(240, 230, 140, 0.3)';
         iq.borderColor = 'rgba(240, 230, 140, 1)';
         iq.stackingGroupId = layerQuad.stackingGroupId;
-        iq.selectionToSetIfClicked = new tv.e.cc.LayerRectSelection(
+        iq.selectionToSetIfClicked = new tr.e.cc.LayerRectSelection(
             layer, 'Unrecorded area', rect, rect);
         quads.push(iq);
       }
@@ -761,18 +761,18 @@
           iq.borderColor = borderColor.toString();
           iq.borderWidth = 4.0;
           iq.stackingGroupId = stackingGroupId;
-          iq.selectionToSetIfClicked = new tv.e.cc.LayerRectSelection(
+          iq.selectionToSetIfClicked = new tr.e.cc.LayerRectSelection(
               layer, label, rect, rect);
           quads.push(iq);
         }
       }
 
       processRegion(layer.touchEventHandlerRegion, 'Touch listener',
-                    tv.b.Color.fromString('rgb(228, 226, 27)'));
+                    tr.b.Color.fromString('rgb(228, 226, 27)'));
       processRegion(layer.wheelEventHandlerRegion, 'Wheel listener',
-                    tv.b.Color.fromString('rgb(176, 205, 29)'));
+                    tr.b.Color.fromString('rgb(176, 205, 29)'));
       processRegion(layer.nonFastScrollableRegion, 'Repaints on scroll',
-                    tv.b.Color.fromString('rgb(213, 134, 32)'));
+                    tr.b.Color.fromString('rgb(213, 134, 32)'));
     },
 
     appendTileCoverageRectQuads_: function(
@@ -805,21 +805,21 @@
 
         quad.backgroundColor = 'rgba(0, 0, 0, 0)';
         quad.stackingGroupId = layerQuad.stackingGroupId;
-        var type = tv.e.cc.tileTypes.missing;
+        var type = tr.e.cc.tileTypes.missing;
         if (tile) {
           type = tile.getTypeForLayer(layer);
           quad.backgroundColor = heatmapResult[heatIndex].color;
           ++heatIndex;
         }
 
-        quad.borderColor = tv.e.cc.tileBorder[type].color;
-        quad.borderWidth = tv.e.cc.tileBorder[type].width;
+        quad.borderColor = tr.e.cc.tileBorder[type].color;
+        quad.borderWidth = tr.e.cc.tileBorder[type].width;
         var label;
         if (tile)
           label = 'coverageRect';
         else
           label = 'checkerboard coverageRect';
-        quad.selectionToSetIfClicked = new tv.e.cc.LayerRectSelection(
+        quad.selectionToSetIfClicked = new tr.e.cc.LayerRectSelection(
             layer, label, rect, layer.tileCoverageRects[ct]);
 
         quads.push(quad);
@@ -845,7 +845,7 @@
         quad.borderWidth = 2;
         var label;
         label = 'Layout rect';
-        quad.selectionToSetIfClicked = new tv.e.cc.LayerRectSelection(
+        quad.selectionToSetIfClicked = new tr.e.cc.LayerRectSelection(
             layer, label, rect);
 
         quads.push(quad);
@@ -865,7 +865,7 @@
     },
 
     getMinMaxForHeatmap_: function(tiles, heatmapType) {
-      var range = new tv.b.Range();
+      var range = new tr.b.Range();
       if (heatmapType == TILE_HEATMAP_TYPE.USING_GPU_MEMORY) {
         range.addValue(0);
         range.addValue(1);
@@ -944,8 +944,8 @@
         quad.stackingGroupId = layerQuad.stackingGroupId;
 
         var type = tile.getTypeForLayer(layer);
-        quad.borderColor = tv.e.cc.tileBorder[type].color;
-        quad.borderWidth = tv.e.cc.tileBorder[type].width;
+        quad.borderColor = tr.e.cc.tileBorder[type].color;
+        quad.borderWidth = tr.e.cc.tileBorder[type].width;
 
         quad.backgroundColor = heatmapResult[i].color;
         var data = {
@@ -953,7 +953,7 @@
         };
         if (heatmapType !== TILE_HEATMAP_TYPE.NONE)
           data[heatmapType] = heatmapResult[i].value;
-        quad.selectionToSetIfClicked = new tv.e.cc.TileSelection(tile, data);
+        quad.selectionToSetIfClicked = new tr.e.cc.TileSelection(tile, data);
         quads.push(quad);
       }
     },
@@ -966,11 +966,11 @@
         var unitRect = rect.asUVRectInside(layer.bounds);
         var quad = layerQuad.projectUnitRect(unitRect);
 
-        var colorId = tv.b.ui.getColorIdForGeneralPurposeString(
+        var colorId = tr.b.ui.getColorIdForGeneralPurposeString(
             highlight.colorKey);
-        colorId += tv.b.ui.getColorPaletteHighlightIdBoost();
+        colorId += tr.b.ui.getColorPaletteHighlightIdBoost();
 
-        var color = tv.b.Color.fromString(tv.b.ui.getColorPalette()[colorId]);
+        var color = tr.b.Color.fromString(tr.b.ui.getColorPalette()[colorId]);
 
         var quadForDrawing = quad.clone();
         quadForDrawing.backgroundColor = color.withAlpha(0.5).toString();
@@ -1037,7 +1037,7 @@
           layerQuad.borderColor = 'rgba(0,0,0,0.75)';
         }
         layerQuad.stackingGroupId = nextStackingGroupId++;
-        layerQuad.selectionToSetIfClicked = new tv.e.cc.LayerSelection(layer);
+        layerQuad.selectionToSetIfClicked = new tr.e.cc.LayerSelection(layer);
         layerQuad.layer = layer;
         if (this.showOtherLayers && this.selectedLayer == layer)
           layerQuad.upperBorderColor = 'rgb(156,189,45)';
@@ -1098,7 +1098,7 @@
         for (var i = 0; i < tracedInputLatencies.length; i++) {
           var coordinatesArray = tracedInputLatencies[i].args.data.coordinates;
           for (var j = 0; j < coordinatesArray.length; j++) {
-            var inputQuad = tv.b.Quad.fromXYWH(
+            var inputQuad = tr.b.Quad.fromXYWH(
                 coordinatesArray[j].x - 25,
                 coordinatesArray[j].y - 25,
                 50,
@@ -1118,7 +1118,7 @@
         this.infoBar_.removeAllButtons();
         this.infoBar_.message = 'Some problems were encountered...';
         this.infoBar_.addButton('More info...', function(e) {
-          var overlay = new tv.b.ui.Overlay();
+          var overlay = new tr.b.ui.Overlay();
           overlay.textContent = '';
           infoBarMessages.forEach(function(message) {
             var title = document.createElement('h3');
@@ -1148,10 +1148,10 @@
       var renderProcess = lthi.objectInstance.parent;
       var tasks = [];
       renderProcess.iterateAllEvents(function(event) {
-        if (!(event instanceof tv.c.trace_model.Slice))
+        if (!(event instanceof tr.model.Slice))
           return;
 
-        var tile = tv.e.cc.getTileFromRasterTaskSlice(event);
+        var tile = tr.e.cc.getTileFromRasterTaskSlice(event);
         if (tile === undefined)
           return false;
 
@@ -1174,8 +1174,8 @@
 
     onWhatRasterizedLinkClicked_: function() {
       var tasks = this.getWhatRasterized_();
-      var event = new tv.c.RequestSelectionChangeEvent();
-      event.selection = new tv.c.Selection(tasks);
+      var event = new tr.c.RequestSelectionChangeEvent();
+      event.selection = new tr.c.Selection(tasks);
       this.dispatchEvent(event);
     }
   };
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view_test.html
index a74aec1..e622b05 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_tree_quad_stack_view_test.html
@@ -8,15 +8,16 @@
 <link rel="import" href="/extras/chrome/cc/cc.html">
 <link rel="import" href="/extras/chrome/cc/layer_tree_quad_stack_view.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
+
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('tileCoverageRectCount', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
+    var m = new tr.Model(g_catLTHIEvents);
     var p = m.processes[1];
 
     var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
@@ -24,9 +25,9 @@
     var numLayers = lthi.activeTree.renderSurfaceLayerList.length;
     var layer = lthi.activeTree.renderSurfaceLayerList[numLayers - 1];
 
-    var view = new tv.e.cc.LayerTreeQuadStackView();
+    var view = new tr.e.cc.LayerTreeQuadStackView();
     view.layerTreeImpl = lthi.activeTree;
-    view.selection = new tv.e.cc.LayerSelection(layer);
+    view.selection = new tr.e.cc.LayerSelection(layer);
     view.howToShowTiles = 'none';
     view.showInvalidations = false;
     view.showContents = false;
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_view.html
index 5a8981f..cec4efb 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_view.html
@@ -13,7 +13,7 @@
 <link rel="import" href="/base/raf.html">
 <link rel="import" href="/base/settings.html">
 <link rel="import" href="/base/ui/drag_handle.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
@@ -22,20 +22,20 @@
  * @fileoverview LayerView coordinates graphical and analysis views of layers.
  */
 
-tv.exportTo('tv.e.cc', function() {
-  var constants = tv.e.cc.constants;
+tr.exportTo('tr.e.cc', function() {
+  var constants = tr.e.cc.constants;
 
   /**
    * @constructor
    */
-  var LayerView = tv.b.ui.define('layer-view');
+  var LayerView = tr.b.ui.define('layer-view');
 
   LayerView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
 
     decorate: function() {
-      this.layerTreeQuadStackView_ = new tv.e.cc.LayerTreeQuadStackView();
-      this.dragBar_ = new tv.b.ui.DragHandle();
+      this.layerTreeQuadStackView_ = new tr.e.cc.LayerTreeQuadStackView();
+      this.dragBar_ = new tr.b.ui.DragHandle();
       this.analysisEl_ = document.createElement('layer-view-analysis');
       this.analysisEl_.addEventListener('requestSelectionChange',
           this.onRequestSelectionChangeFromAnalysisEl_.bind(this));
@@ -101,20 +101,20 @@
         this.layerTreeQuadStackView_.style.height =
             window.getComputedStyle(this).height;
       }
-      tv.b.dispatchSimpleEvent(this, 'selection-change');
+      tr.b.dispatchSimpleEvent(this, 'selection-change');
     },
 
     createPictureBtn_: function(pictures) {
       if (!(pictures instanceof Array))
         pictures = [pictures];
 
-      var link = document.createElement('tv-c-analysis-link');
+      var link = document.createElement('tr-c-a-analysis-link');
       link.selection = function() {
-        var layeredPicture = new tv.e.cc.LayeredPicture(pictures);
-        var snapshot = new tv.e.cc.PictureSnapshot(layeredPicture);
+        var layeredPicture = new tr.e.cc.LayeredPicture(pictures);
+        var snapshot = new tr.e.cc.PictureSnapshot(layeredPicture);
         snapshot.picture = layeredPicture;
 
-        var selection = new tv.c.Selection();
+        var selection = new tr.c.Selection();
         selection.push(snapshot);
         return selection;
       };
@@ -123,7 +123,7 @@
     },
 
     onRequestSelectionChangeFromAnalysisEl_: function(e) {
-      if (!(e.selection instanceof tv.e.cc.Selection))
+      if (!(e.selection instanceof tr.e.cc.Selection))
         return;
 
       e.stopPropagation();
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/layer_view_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/layer_view_test.html
index bc2be96..d97007d 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/layer_view_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/layer_view_test.html
@@ -8,16 +8,16 @@
 <link rel="import" href="/extras/chrome/cc/cc.html">
 <link rel="import" href="/extras/chrome/cc/layer_view.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
+    var m = new tr.Model(g_catLTHIEvents);
     var p = m.processes[1];
 
     var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
@@ -25,16 +25,16 @@
     var numLayers = lthi.activeTree.renderSurfaceLayerList.length;
     var layer = lthi.activeTree.renderSurfaceLayerList[numLayers - 1];
 
-    var view = new tv.e.cc.LayerView();
+    var view = new tr.e.cc.LayerView();
     view.style.height = '500px';
     view.layerTreeImpl = lthi.activeTree;
-    view.selection = new tv.e.cc.LayerSelection(layer);
+    view.selection = new tr.e.cc.LayerSelection(layer);
 
     this.addHTMLOutput(view);
   });
 
   test('instantiate_withTileHighlight', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
+    var m = new tr.Model(g_catLTHIEvents);
     var p = m.processes[1];
 
     var instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
@@ -43,10 +43,10 @@
     var layer = lthi.activeTree.renderSurfaceLayerList[numLayers - 1];
     var tile = lthi.activeTiles[0];
 
-    var view = new tv.e.cc.LayerView();
+    var view = new tr.e.cc.LayerView();
     view.style.height = '500px';
     view.layerTreeImpl = lthi.activeTree;
-    view.selection = new tv.e.cc.TileSelection(tile);
+    view.selection = new tr.e.cc.TileSelection(tile);
     this.addHTMLOutput(view);
   });
 });
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture.html
index 99db6d4..0939216 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture.html
@@ -10,13 +10,13 @@
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/base/rect.html">
 <link rel="import" href="/base/raf.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.cc', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   // Number of pictures created. Used as an uniqueId because we are immutable.
   var PictureCount = 0;
@@ -26,7 +26,7 @@
     this.skp64_ = skp64;
     this.layerRect_ = layerRect;
 
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
   }
 
   Picture.prototype = {
@@ -121,13 +121,13 @@
      *     rasterize up to. If not defined, the entire SkPicture is rasterized.
      * @param {{opt_showOverdraw: bool, params}} Defines whether pixel overdraw
            should be visualized in the image.
-     * @param {function(tv.e.cc.PictureAsImageData)} The callback function that
+     * @param {function(tr.e.cc.PictureAsImageData)} The callback function that
      *     is called after rasterization is complete or fails.
      */
     rasterize: function(params, rasterCompleteCallback) {
       if (!PictureSnapshot.CanRasterize() || !PictureSnapshot.CanGetOps()) {
-        rasterCompleteCallback(new tv.e.cc.PictureAsImageData(
-            this, tv.e.cc.PictureSnapshot.HowToEnablePictureDebugging()));
+        rasterCompleteCallback(new tr.e.cc.PictureAsImageData(
+            this, tr.e.cc.PictureSnapshot.HowToEnablePictureDebugging()));
         return;
       }
 
@@ -151,18 +151,18 @@
         canvas.height = raster.height;
         var imageData = ctx.createImageData(raster.width, raster.height);
         imageData.data.set(new Uint8ClampedArray(raster.data));
-        rasterCompleteCallback(new tv.e.cc.PictureAsImageData(this, imageData));
+        rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this, imageData));
       } else {
         var error = 'Failed to rasterize picture. ' +
                 'Your recording may be from an old Chrome version. ' +
                 'The SkPicture format is not backward compatible.';
-        rasterCompleteCallback(new tv.e.cc.PictureAsImageData(this, error));
+        rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this, error));
       }
     }
   };
 
   function LayeredPicture(pictures) {
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
     this.pictures_ = pictures;
     this.layerRect_ = undefined;
   }
@@ -265,7 +265,7 @@
         }
         this.picturesAsImageData_ = [];
 
-        rasterCompleteCallback(new tv.e.cc.PictureAsImageData(this,
+        rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this,
             ctx.getImageData(this.layerRect.x, this.layerRect.y,
                              this.layerRect.width, this.layerRect.height)));
       }.bind(this);
@@ -349,7 +349,7 @@
     __proto__: ObjectSnapshot.prototype,
 
     preInitialize: function() {
-      tv.e.cc.preInitializeObject(this);
+      tr.e.cc.preInitializeObject(this);
       this.rasterResult_ = undefined;
     },
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_as_image_data.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_as_image_data.html
index 4775f71..3b3128f 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_as_image_data.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_as_image_data.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /**
    * @constructor
    */
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger.html
index 69f7d9b..6e63e08 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger.html
@@ -26,7 +26,7 @@
     display: -webkit-flex;
   }
 
-  * /deep/ picture-debugger > tv-c-analysis-generic-object-view {
+  * /deep/ picture-debugger > tr-c-a-generic-object-view {
     -webkit-flex-direction: column;
     display: -webkit-flex;
     width: 400px;
@@ -103,7 +103,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var THIS_DOC = document.currentScript.ownerDocument;
 
   /**
@@ -112,13 +112,13 @@
    *
    * @constructor
    */
-  var PictureDebugger = tv.b.ui.define('picture-debugger');
+  var PictureDebugger = tr.b.ui.define('picture-debugger');
 
   PictureDebugger.prototype = {
     __proto__: HTMLUnknownElement.prototype,
 
     decorate: function() {
-      var node = tv.b.instantiateTemplate('#picture-debugger-template',
+      var node = tr.b.instantiateTemplate('#picture-debugger-template',
           THIS_DOC);
 
       this.appendChild(node);
@@ -134,8 +134,8 @@
 
       this.filename_ = this.querySelector('.filename');
 
-      this.drawOpsChartSummaryView_ = new tv.e.cc.PictureOpsChartSummaryView();
-      this.drawOpsChartView_ = new tv.e.cc.PictureOpsChartView();
+      this.drawOpsChartSummaryView_ = new tr.e.cc.PictureOpsChartSummaryView();
+      this.drawOpsChartView_ = new tr.e.cc.PictureOpsChartView();
       this.drawOpsChartView_.addEventListener(
           'selection-changed', this.onChartBarClicked_.bind(this));
 
@@ -145,12 +145,12 @@
 
       this.trackMouse_();
 
-      var overdrawCheckbox = tv.b.ui.createCheckBox(
+      var overdrawCheckbox = tr.b.ui.createCheckBox(
           this, 'showOverdraw',
           'pictureView.showOverdraw', false,
           'Show overdraw');
 
-      var chartCheckbox = tv.b.ui.createCheckBox(
+      var chartCheckbox = tr.b.ui.createCheckBox(
           this, 'showSummaryChart',
           'pictureView.showSummaryChart', false,
           'Show timing summary');
@@ -159,7 +159,7 @@
       pictureInfo.appendChild(overdrawCheckbox);
       pictureInfo.appendChild(chartCheckbox);
 
-      this.drawOpsView_ = new tv.e.cc.PictureOpsListView();
+      this.drawOpsView_ = new tr.e.cc.PictureOpsListView();
       this.drawOpsView_.addEventListener(
           'selection-changed', this.onChangeDrawOps_.bind(this));
 
@@ -167,7 +167,7 @@
       leftPanel.appendChild(this.drawOpsChartSummaryView_);
       leftPanel.appendChild(this.drawOpsView_);
 
-      var middleDragHandle = new tv.b.ui.DragHandle();
+      var middleDragHandle = new tr.b.ui.DragHandle();
       middleDragHandle.horizontal = false;
       middleDragHandle.target = leftPanel;
 
@@ -176,14 +176,14 @@
           this.drawOpsChartView_,
           rightPanel.querySelector('picture-ops-chart-view'));
 
-      this.infoBar_ = document.createElement('tv-b-ui-info-bar');
+      this.infoBar_ = document.createElement('tr-b-ui-info-bar');
       this.rasterArea_.appendChild(this.infoBar_);
 
       this.insertBefore(middleDragHandle, rightPanel);
 
       this.picture_ = undefined;
 
-      tv.b.KeyEventManager.instance.addListener(
+      tr.b.KeyEventManager.instance.addListener(
           'keypress', this.onKeyPress_, this);
 
       // Add a mutation observer so that when the view is resized we can
@@ -294,7 +294,7 @@
       if (this.updateContentsPending_)
         return;
       this.updateContentsPending_ = true;
-      tv.b.requestAnimationFrameInThisFrameIfPossible(
+      tr.b.requestAnimationFrameInThisFrameIfPossible(
           this.updateContents_.bind(this)
       );
     },
@@ -320,7 +320,7 @@
       if (this.pictureAsImageData_.error) {
         this.infoBar_.message = 'Cannot rasterize...';
         this.infoBar_.addButton('More info...', function(e) {
-          var overlay = new tv.b.ui.Overlay();
+          var overlay = new tr.b.ui.Overlay();
           overlay.textContent = this.pictureAsImageData_.error;
           overlay.visible = true;
           e.stopPropagation();
@@ -373,7 +373,7 @@
         this.selectedOpIndex = 0;
         return;
       }
-      this.selectedOpIndex = tv.b.clamp(
+      this.selectedOpIndex = tr.b.clamp(
           this.selectedOpIndex + increment,
           0, this.numOps);
     },
@@ -417,13 +417,13 @@
     },
 
     trackMouse_: function() {
-      this.mouseModeSelector_ = new tv.b.ui.MouseModeSelector(this.rasterArea_);
+      this.mouseModeSelector_ = new tr.b.ui.MouseModeSelector(this.rasterArea_);
       this.rasterArea_.appendChild(this.mouseModeSelector_);
 
       this.mouseModeSelector_.supportedModeMask =
-          tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
-      this.mouseModeSelector_.mode = tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
-      this.mouseModeSelector_.defaultMode = tv.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
+          tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
+      this.mouseModeSelector_.mode = tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
+      this.mouseModeSelector_.defaultMode = tr.b.ui.MOUSE_SELECTOR_MODE.ZOOM;
       this.mouseModeSelector_.settingsKey = 'pictureDebugger.mouseModeSelector';
 
       this.mouseModeSelector_.addEventListener('beginzoom',
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger_test.html
index ac2d455..c1839ba 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_debugger_test.html
@@ -11,9 +11,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('instantiate', function() {
-    var picture = new tv.e.cc.PictureSnapshot({id: '31415'}, 10, {
+    var picture = new tr.e.cc.PictureSnapshot({id: '31415'}, 10, {
       'params': {
         'opaque_rect': [-15, -15, 0, 0],
         'layer_rect': [-15, -15, 46, 833]
@@ -23,7 +23,7 @@
     picture.preInitialize();
     picture.initialize();
 
-    var dbg = new tv.e.cc.PictureDebugger();
+    var dbg = new tr.e.cc.PictureDebugger();
     this.addHTMLOutput(dbg);
     dbg.picture = picture;
     dbg.style.border = '1px solid black';
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.html
index a717fd7..b739dd2 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_summary_view.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var OPS_TIMING_ITERATIONS = 3;
   var CHART_PADDING_LEFT = 65;
   var CHART_PADDING_RIGHT = 40;
@@ -34,7 +34,7 @@
    *
    * @constructor
    */
-  var PictureOpsChartSummaryView = tv.b.ui.define(
+  var PictureOpsChartSummaryView = tr.b.ui.define(
       'picture-ops-chart-summary-view');
 
   PictureOpsChartSummaryView.prototype = {
@@ -121,7 +121,7 @@
         this.currentBarMouseOverTarget_ = Math.floor(
             (x - chartLeft) / chartInnerWidth * this.opsTimingData_.length);
 
-        this.currentBarMouseOverTarget_ = tv.b.clamp(
+        this.currentBarMouseOverTarget_ = tr.b.clamp(
             this.currentBarMouseOverTarget_, 0, this.opsTimingData_.length - 1);
 
       }
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_view.html
index 36c35ce..8273d19 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_chart_view.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var BAR_PADDING = 1;
   var BAR_WIDTH = 5;
   var CHART_PADDING_LEFT = 65;
@@ -33,7 +33,7 @@
    *
    * @constructor
    */
-  var PictureOpsChartView = tv.b.ui.define('picture-ops-chart-view');
+  var PictureOpsChartView = tr.b.ui.define('picture-ops-chart-view');
 
   PictureOpsChartView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
@@ -63,7 +63,7 @@
       this.chart_.addEventListener('mousemove', this.onMouseMove_.bind(this));
 
       this.usePercentileScale_ = false;
-      this.usePercentileScaleCheckbox_ = tv.b.ui.createCheckBox(
+      this.usePercentileScaleCheckbox_ = tr.b.ui.createCheckBox(
           this, 'usePercentileScale',
           'PictureOpsChartView.usePercentileScale', false,
           'Limit to 95%-ile');
@@ -161,7 +161,7 @@
       index = Math.floor((x - chartLeft) / totalBarWidth *
           this.pictureOps_.length);
 
-      index = tv.b.clamp(index, 0, this.pictureOps_.length - 1);
+      index = tr.b.clamp(index, 0, this.pictureOps_.length - 1);
 
       return index;
     },
@@ -181,7 +181,7 @@
 
       e.preventDefault();
 
-      tv.b.dispatchSimpleEvent(this, 'selection-changed', false);
+      tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
     },
 
     onMouseMove_: function(e) {
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view.html
index f3e0d5e..ace9bd8 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view.html
@@ -15,7 +15,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var OPS_TIMING_ITERATIONS = 3; // Iterations to average op timing info over.
   var ANNOTATION = 'Comment';
   var BEGIN_ANNOTATION = 'BeginCommentGroup';
@@ -24,18 +24,18 @@
   var ANNOTATION_CLASS = 'CLASS: ';
   var ANNOTATION_TAG = 'TAG: ';
 
-  var constants = tv.e.cc.constants;
+  var constants = tr.e.cc.constants;
 
   /**
    * @constructor
    */
-  var PictureOpsListView = tv.b.ui.define('picture-ops-list-view');
+  var PictureOpsListView = tr.b.ui.define('picture-ops-list-view');
 
   PictureOpsListView.prototype = {
     __proto__: HTMLUnknownElement.prototype,
 
     decorate: function() {
-      this.opsList_ = new tv.b.ui.ListView();
+      this.opsList_ = new tr.b.ui.ListView();
       this.appendChild(this.opsList_);
 
       this.selectedOp_ = undefined;
@@ -138,7 +138,7 @@
         }
       }
 
-      tv.b.dispatchSimpleEvent(this, 'selection-changed', false);
+      tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
     },
 
     get numOps() {
@@ -159,7 +159,7 @@
         if (s < 0) throw new Error('Invalid index');
         if (s >= this.numOps) throw new Error('Invalid index');
         this.opsList_.selectedElement = this.opsList_.getElementByIndex(s + 1);
-        tv.b.scrollIntoViewIfNeeded(this.opsList_.selectedElement);
+        tr.b.scrollIntoViewIfNeeded(this.opsList_.selectedElement);
       }
     },
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view_test.html
index 2ee92f7..67777e2 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_ops_list_view_test.html
@@ -8,21 +8,21 @@
 <link rel="import" href="/extras/chrome/cc/picture_ops_list_view.html">
 <link rel="import" href="/extras/chrome/cc/picture.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var PictureOpsListView = tv.e.cc.PictureOpsListView;
+tr.b.unittest.testSuite(function() {
+  var PictureOpsListView = tr.e.cc.PictureOpsListView;
 
   test('instantiate', function() {
-    if (!tv.e.cc.PictureSnapshot.CanRasterize())
+    if (!tr.e.cc.PictureSnapshot.CanRasterize())
       return;
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
     var snapshot = instance.snapshots[0];
@@ -33,10 +33,10 @@
   });
 
   test('selection', function() {
-    if (!tv.e.cc.PictureSnapshot.CanRasterize())
+    if (!tr.e.cc.PictureSnapshot.CanRasterize())
       return;
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
     var snapshot = instance.snapshots[0];
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_test.html
index 04e8f19..e0387cc 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_test.html
@@ -8,28 +8,28 @@
 <link rel="import" href="/extras/chrome/cc/cc.html">
 <link rel="import" href="/extras/chrome/cc/picture.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
     var snapshot = instance.snapshots[0];
 
-    assert.instanceOf(snapshot, tv.e.cc.PictureSnapshot);
+    assert.instanceOf(snapshot, tr.e.cc.PictureSnapshot);
     instance.wasDeleted(150);
   });
 
   test('getOps', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
     var snapshot = instance.snapshots[0];
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/picture_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/picture_view.html
index 601e89f..4d1a94d 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/picture_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/picture_view.html
@@ -11,26 +11,26 @@
 <link rel="import" href="/extras/chrome/cc/picture_debugger.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
 <link rel="import" href="/core/analysis/object_snapshot_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /*
    * Displays a picture snapshot in a human readable form.
    * @constructor
    */
-  var PictureSnapshotView = tv.b.ui.define(
+  var PictureSnapshotView = tr.b.ui.define(
       'picture-snapshot-view',
-      tv.c.analysis.ObjectSnapshotView);
+      tr.c.analysis.ObjectSnapshotView);
 
   PictureSnapshotView.prototype = {
-    __proto__: tv.c.analysis.ObjectSnapshotView.prototype,
+    __proto__: tr.c.analysis.ObjectSnapshotView.prototype,
 
     decorate: function() {
       this.classList.add('picture-snapshot-view');
-      this.pictureDebugger_ = new tv.e.cc.PictureDebugger();
+      this.pictureDebugger_ = new tr.e.cc.PictureDebugger();
       this.appendChild(this.pictureDebugger_);
     },
 
@@ -40,7 +40,7 @@
     }
   };
 
-  tv.c.analysis.ObjectSnapshotView.register(
+  tr.c.analysis.ObjectSnapshotView.register(
       PictureSnapshotView,
       {
         typeNames: ['cc::Picture', 'cc::LayeredPicture'],
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task.html b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task.html
index ea20343..131108a 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
 
   var knownRasterTaskNames = [
       'TileManager::RunRasterTask',
@@ -45,7 +45,7 @@
       return tileData.tile_id;
 
     var tile = tileData.tileId;
-    if (!(tile instanceof tv.e.cc.TileSnapshot))
+    if (!(tile instanceof tr.e.cc.TileSnapshot))
       return undefined;
     return tileData.tileId;
   }
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection.html b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection.html
index 4556a46..5532510 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection.html
@@ -12,25 +12,25 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /**
    * @constructor
    */
   function RasterTaskSelection(selection) {
-    tv.e.cc.Selection.call(this);
+    tr.e.cc.Selection.call(this);
     var whySupported = RasterTaskSelection.whySuported(selection);
     if (!whySupported.ok)
       throw new Error('Fail: ' + whySupported.why);
-    this.slices_ = tv.b.asArray(selection);
+    this.slices_ = tr.b.asArray(selection);
     this.tiles_ = this.slices_.map(function(slice) {
-      var tile = tv.e.cc.getTileFromRasterTaskSlice(slice);
+      var tile = tr.e.cc.getTileFromRasterTaskSlice(slice);
       if (tile === undefined)
         throw new Error('This should never happen due to .supports check.');
       return tile;
     });
   }
   RasterTaskSelection.whySuported = function(selection) {
-    if (!(selection instanceof tv.c.Selection))
+    if (!(selection instanceof tr.c.Selection))
       return {ok: false, why: 'Must be selection'};
 
     if (selection.length === 0)
@@ -39,10 +39,10 @@
     var tile0;
     for (var i = 0; i < selection.length; i++) {
       var event = selection[i];
-      if (!(event instanceof tv.c.trace_model.Slice))
+      if (!(event instanceof tr.model.Slice))
         return {ok: false, why: 'Not a slice'};
 
-      var tile = tv.e.cc.getTileFromRasterTaskSlice(selection[i]);
+      var tile = tr.e.cc.getTileFromRasterTaskSlice(selection[i]);
       if (tile === undefined)
         return {ok: false, why: 'No tile found'};
 
@@ -65,7 +65,7 @@
   };
 
   RasterTaskSelection.prototype = {
-    __proto__: tv.e.cc.Selection.prototype,
+    __proto__: tr.e.cc.Selection.prototype,
 
     get specicifity() {
       return 3;
@@ -96,14 +96,14 @@
     },
 
     createAnalysis: function() {
-      var sel = new tv.c.Selection();
+      var sel = new tr.c.Selection();
       this.slices_.forEach(function(slice) {
         sel.push(slice);
       });
 
       var analysis;
       if (sel.length == 1)
-        analysis = document.createElement('tv-c-a-single-event-sub-view');
+        analysis = document.createElement('tr-c-a-single-event-sub-view');
       else
         analysis = new RasterTaskView();
       analysis.selection = sel;
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection_test.html
index d3adf39..fd49108 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_selection_test.html
@@ -7,27 +7,29 @@
 <link rel="import" href="/base/utils.html">
 <link rel="import" href="/extras/chrome/cc/raster_task_selection.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
+
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
+
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
+    var m = new tr.Model(g_catLTHIEvents);
     var p = m.processes[1];
     var rasterTasks = p.threads[1].sliceGroup.slices.filter(function(slice) {
       return slice.title == 'RasterTask';
     });
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(rasterTasks[0]);
     selection.push(rasterTasks[1]);
 
-    assert.isTrue(tv.e.cc.RasterTaskSelection.supports(selection));
-    var selection = new tv.e.cc.RasterTaskSelection(selection);
+    assert.isTrue(tr.e.cc.RasterTaskSelection.supports(selection));
+    var selection = new tr.e.cc.RasterTaskSelection(selection);
     var highlights = selection.extraHighlightsByLayerId;
-    assert.equal(tv.b.dictionaryLength(highlights), 1);
+    assert.equal(tr.b.dictionaryLength(highlights), 1);
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view.html
index 45f4729..c26eb6d 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view.html
@@ -7,10 +7,10 @@
 <link rel="import" href="/extras/chrome/cc/raster_task.html">
 <link rel="import" href="/extras/chrome/cc/selection.html">
 <link rel="import" href="/core/analysis/analysis_sub_view.html">
-<link rel="import" href="/core/analysis/time_span.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/units/time_duration_span.html">
+<link rel="import" href="/base/ui/table.html">
 
-<polymer-element name="tv-e-cc-raster-task-view"
+<polymer-element name="tr-e-cc-raster-task-view"
     constructor="RasterTaskView">
   <template>
     <style>
@@ -24,9 +24,9 @@
     </style>
     <div id="heading">
       Rasterization costs in
-      <tv-c-analysis-link id="link"></tv-c-analysis-link>
+      <tr-c-a-analysis-link id="link"></tr-c-a-analysis-link>
     </div>
-    <tracing-analysis-nested-table id="content"></tracing-analysis-nested-table>
+    <tr-b-ui-table id="content"></tr-b-ui-table>
   </template>
   <script>
   'use strict';
@@ -49,10 +49,10 @@
             if (row.isTotals)
               return 'Totals';
             if (row.layer) {
-              var linkEl = document.createElement('tv-c-analysis-link');
+              var linkEl = document.createElement('tr-c-a-analysis-link');
               linkEl.setSelectionAndContent(
                 function() {
-                  return new tv.e.cc.LayerSelection(costs.layer);
+                  return new tr.e.cc.LayerSelection(costs.layer);
                 },
                 'Layer ' + row.layerId);
               return linkEl;
@@ -82,7 +82,7 @@
         {
           title: 'Wall Duration (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.duration);
+            return tr.b.units.createTimeSpan(row.duration);
           },
           cmp: function(a, b) { return a.duration - b.duration; }
         }
@@ -92,7 +92,7 @@
         columns.push({
           title: 'CPU Duration (ms)',
           value: function(row) {
-            return tv.c.analysis.createTimeSpan(row.duration);
+            return tr.b.units.createTimeSpan(row.duration);
           },
           cmp: function(a, b) { return a.cpuDuration - b.cpuDuration; }
         });
@@ -123,10 +123,10 @@
       }
 
       // LTHI link.
-      var lthi = tv.e.cc.getTileFromRasterTaskSlice(
+      var lthi = tr.e.cc.getTileFromRasterTaskSlice(
           this.selection_[0]).containingSnapshot;
       this.$.link.setSelectionAndContent(function() {
-          return new tv.c.Selection(lthi);
+          return new tr.c.Selection(lthi);
       }, lthi.userFriendlyName);
 
       // Get costs by layer.
@@ -162,7 +162,7 @@
       var tilesThatWeHaveSeen = {};
 
       this.selection_.forEach(function(slice) {
-        var tile = tv.e.cc.getTileFromRasterTaskSlice(slice);
+        var tile = tr.e.cc.getTileFromRasterTaskSlice(slice);
         var curCosts = getCurrentCostsForLayerId(tile);
 
         if (!tilesThatWeHaveSeen[tile.objectInstance.id]) {
@@ -170,7 +170,7 @@
           curCosts.numTiles += 1;
         }
 
-        if (tv.e.cc.isSliceDoingAnalysis(slice)) {
+        if (tr.e.cc.isSliceDoingAnalysis(slice)) {
           curCosts.numAnalysisTasks += 1;
           totalNumAnalyzeTasks += 1;
         } else {
@@ -188,14 +188,14 @@
 
       // Apply to the table.
       this.updateColumns_(hadCpuDurations);
-      table.tableRows = tv.b.dictionaryValues(costsByLayerId);
+      table.tableRows = tr.b.dictionaryValues(costsByLayerId);
       table.rebuild();
 
       // Footer.
       table.footerRows = [
         {
           isTotals: true,
-          numTiles: tv.b.dictionaryLength(tilesThatWeHaveSeen),
+          numTiles: tr.b.dictionaryLength(tilesThatWeHaveSeen),
           numAnalysisTasks: totalNumAnalyzeTasks,
           numRasterTasks: totalNumRasterizeTasks,
           duration: totalDuration,
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view_test.html
index e506041..bb1b230 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/raster_task_view_test.html
@@ -13,20 +13,22 @@
 <link rel="import" href="/extras/chrome/cc/raster_task_selection.html">
 <link rel="import" href="/extras/chrome/cc/layer_tree_host_impl_view.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
+
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
+
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function createSelection() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
+    var m = new tr.Model(g_catLTHIEvents);
     var p = m.processes[1];
     var rasterTasks = p.threads[1].sliceGroup.slices.filter(function(slice) {
       return slice.title == 'RasterTask' || slice.title == 'AnalyzeTask';
     });
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.model = m;
 
     selection.push(rasterTasks[0]);
@@ -46,15 +48,15 @@
     var selection = createSelection();
 
     var timelineView = {model: selection.model};
-    var selectionController = new tv.c.SelectionController(timelineView);
+    var selectionController = new tr.c.SelectionController(timelineView);
 
-    var analysisEl = document.createElement('tv-c-a-analysis-view');
+    var analysisEl = document.createElement('tr-c-a-analysis-view');
     analysisEl.selectionController = selectionController;
     selectionController.changeSelectionFromTimeline(selection);
 
     assert.isDefined(analysisEl.querySelector('RasterTaskView'));
-    var sv = tv.b.findDeepElementMatching(
-        analysisEl, 'tv-c-a-multi-thread-slice-sub-view');
+    var sv = tr.b.findDeepElementMatching(
+        analysisEl, 'tr-c-a-multi-thread-slice-sub-view');
     assert.isTrue(sv.requiresTallView);
     this.addHTMLOutput(analysisEl);
   });
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/region.html b/trace-viewer/trace_viewer/extras/chrome/cc/region.html
index 1683ee9..f89d858 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/region.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/region.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /**
    * @constructor
    */
@@ -23,7 +23,7 @@
 
     var r = new Region();
     for (var i = 0; i < array.length; i += 4) {
-      r.rects.push(tv.b.Rect.fromXYWH(array[i], array[i + 1],
+      r.rects.push(tr.b.Rect.fromXYWH(array[i], array[i + 1],
                                       array[i + 2], array[i + 3]));
     }
     return r;
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/render_pass.html b/trace-viewer/trace_viewer/extras/chrome/cc/render_pass.html
index 139c068..7bb88cc 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/render_pass.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/render_pass.html
@@ -7,13 +7,13 @@
 
 <link rel="import" href="/extras/chrome/cc/util.html">
 <link rel="import" href="/base/rect.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.cc', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * @constructor
@@ -26,11 +26,11 @@
     __proto__: ObjectSnapshot.prototype,
 
     preInitialize: function() {
-      tv.e.cc.preInitializeObject(this);
+      tr.e.cc.preInitializeObject(this);
     },
 
     initialize: function() {
-      tv.e.cc.moveRequiredFieldsFromArgsToToplevel(
+      tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
           this, ['quadList']);
     }
   };
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/selection.html b/trace-viewer/trace_viewer/extras/chrome/cc/selection.html
index 7035309..93230c0 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/selection.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/selection.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   function Selection() {
     this.selectionToSetIfClicked = undefined;
   };
@@ -96,7 +96,7 @@
 
     createAnalysis: function() {
       var dataView = document.createElement(
-          'tv-c-analysis-generic-object-view-with-label');
+          'tr-c-a-generic-object-view-with-label');
       dataView.label = 'RenderPass ' + this.renderPassId_;
       dataView.object = this.renderPass_.args;
       return dataView;
@@ -137,7 +137,7 @@
 
     createAnalysis: function() {
       var dataView = document.createElement(
-          'tv-c-analysis-generic-object-view-with-label');
+          'tr-c-a-generic-object-view-with-label');
       dataView.label = 'Layer ' + this.layer_.layerId;
       if (this.layer_.usingGpuRasterization)
         dataView.label += ' (GPU-rasterized)';
@@ -190,7 +190,7 @@
 
     createAnalysis: function() {
       var analysis = document.createElement(
-          'tv-c-analysis-generic-object-view-with-label');
+          'tr-c-a-generic-object-view-with-label');
       analysis.label = 'Tile ' + this.tile_.objectInstance.id + ' on layer ' +
           this.tile_.layerId;
       if (this.data_) {
@@ -251,7 +251,7 @@
 
     createAnalysis: function() {
       var analysis = document.createElement(
-          'tv-c-analysis-generic-object-view-with-label');
+          'tr-c-a-generic-object-view-with-label');
       analysis.label = this.rectType_ + ' on layer ' + this.layer_.layerId;
       analysis.object = this.data_;
       return analysis;
@@ -283,7 +283,7 @@
 
     createAnalysis: function() {
       var analysis = document.createElement(
-          'tv-c-analysis-generic-object-view-with-label');
+          'tr-c-a-generic-object-view-with-label');
       analysis.label = 'Animation Bounds of layer ' + this.layer_.layerId;
       analysis.object = this.rect_;
       return analysis;
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/tile.html b/trace-viewer/trace_viewer/extras/chrome/cc/tile.html
index 2191849..b5f7df5 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/tile.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/tile.html
@@ -8,13 +8,13 @@
 <link rel="import" href="/extras/chrome/cc/util.html">
 <link rel="import" href="/extras/chrome/cc/debug_colors.html">
 <link rel="import" href="/base/rect.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.cc', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * @constructor
@@ -27,11 +27,11 @@
     __proto__: ObjectSnapshot.prototype,
 
     preInitialize: function() {
-      tv.e.cc.preInitializeObject(this);
+      tr.e.cc.preInitializeObject(this);
     },
 
     initialize: function() {
-      tv.e.cc.moveOptionalFieldsFromArgsToToplevel(
+      tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
           this, ['layerId', 'contentsScale', 'contentRect']);
       if (this.args.managedState) {
         this.resolution = this.args.managedState.resolution;
@@ -56,24 +56,24 @@
         this.layerRect = this.contentRect.scale(1.0 / this.contentsScale);
 
       if (this.isSolidColor)
-        this.type_ = tv.e.cc.tileTypes.solidColor;
+        this.type_ = tr.e.cc.tileTypes.solidColor;
       else if (!this.hasResource)
-        this.type_ = tv.e.cc.tileTypes.missing;
+        this.type_ = tr.e.cc.tileTypes.missing;
       else if (this.resolution === 'HIGH_RESOLUTION')
-        this.type_ = tv.e.cc.tileTypes.highRes;
+        this.type_ = tr.e.cc.tileTypes.highRes;
       else if (this.resolution === 'LOW_RESOLUTION')
-        this.type_ = tv.e.cc.tileTypes.lowRes;
+        this.type_ = tr.e.cc.tileTypes.lowRes;
       else
-        this.type_ = tv.e.cc.tileTypes.unknown;
+        this.type_ = tr.e.cc.tileTypes.unknown;
     },
 
     getTypeForLayer: function(layer) {
       var type = this.type_;
-      if (type == tv.e.cc.tileTypes.unknown) {
+      if (type == tr.e.cc.tileTypes.unknown) {
         if (this.contentsScale < layer.idealContentsScale)
-          type = tv.e.cc.tileTypes.extraLowRes;
+          type = tr.e.cc.tileTypes.extraLowRes;
         else if (this.contentsScale > layer.idealContentsScale)
-          type = tv.e.cc.tileTypes.extraHighRes;
+          type = tr.e.cc.tileTypes.extraHighRes;
       }
       return type;
     }
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/tile_coverage_rect.html b/trace-viewer/trace_viewer/extras/chrome/cc/tile_coverage_rect.html
index c951cde..f6d4c7d 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/tile_coverage_rect.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/tile_coverage_rect.html
@@ -9,7 +9,7 @@
 
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /**
    * This class represents a tile (from impl side) and its final rect on the
    * layer. Note that the rect is determined by what is needed to cover all
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/tile_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/tile_test.html
index 86a73ca..2750ddc 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/tile_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/tile_test.html
@@ -8,7 +8,7 @@
 <link rel="import" href="/extras/chrome/cc/tile.html">
 <link rel="import" href="/extras/chrome/cc/tile_view.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/cc/layer_tree_host_impl_test_data.js"></script>
 
@@ -16,14 +16,14 @@
 
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var m = new tv.c.TraceModel(g_catLTHIEvents);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_catLTHIEvents);
+    var p = tr.b.dictionaryValues(m.processes)[0];
     var instance = p.objects.getAllInstancesNamed('cc::Tile')[0];
     var snapshot = instance.snapshots[0];
 
-    assert.instanceOf(snapshot, tv.e.cc.TileSnapshot);
+    assert.instanceOf(snapshot, tr.e.cc.TileSnapshot);
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/tile_view.html b/trace-viewer/trace_viewer/extras/chrome/cc/tile_view.html
index a1f96d6..4cd13f6 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/tile_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/tile_view.html
@@ -8,27 +8,27 @@
 <link rel="import" href="/extras/chrome/cc/tile.html">
 <link rel="import" href="/core/analysis/generic_object_view.html">
 <link rel="import" href="/core/analysis/object_snapshot_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   /*
    * Displays a tile in a human readable form.
    * @constructor
    */
-  var TileSnapshotView = tv.b.ui.define(
+  var TileSnapshotView = tr.b.ui.define(
       'tile-snapshot-view',
-      tv.c.analysis.ObjectSnapshotView);
+      tr.c.analysis.ObjectSnapshotView);
 
   TileSnapshotView.prototype = {
-    __proto__: tv.c.analysis.ObjectSnapshotView.prototype,
+    __proto__: tr.c.analysis.ObjectSnapshotView.prototype,
 
     decorate: function() {
       this.classList.add('tile-snapshot-view');
-      this.layerTreeView_ = new tv.e.cc.LayerTreeHostImplSnapshotView();
+      this.layerTreeView_ = new tr.e.cc.LayerTreeHostImplSnapshotView();
       this.appendChild(this.layerTreeView_);
     },
 
@@ -39,11 +39,11 @@
         return;
 
       this.layerTreeView_.objectSnapshot = layerTreeHostImpl;
-      this.layerTreeView_.selection = new tv.e.cc.TileSelection(tile);
+      this.layerTreeView_.selection = new tr.e.cc.TileSelection(tile);
     }
   };
 
-  tv.c.analysis.ObjectSnapshotView.register(
+  tr.c.analysis.ObjectSnapshotView.register(
       TileSnapshotView,
       {
         typeName: 'cc::Tile',
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/util.html b/trace-viewer/trace_viewer/extras/chrome/cc/util.html
index a743522..b69cfa0 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/util.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/util.html
@@ -7,12 +7,12 @@
 
 <link rel="import" href="/base/quad.html">
 <link rel="import" href="/base/rect.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 <script>
 
 'use strict';
 
-tv.exportTo('tv.e.cc', function() {
+tr.exportTo('tr.e.cc', function() {
   var convertedNameCache = {};
   function convertNameToJSConvention(name) {
     if (name in convertedNameCache)
@@ -38,7 +38,7 @@
   }
 
   function convertObjectFieldNamesToJSConventions(object) {
-    tv.b.iterObjectFieldsRecursively(
+    tr.b.iterObjectFieldsRecursively(
         object,
         function(object, fieldName, fieldValue) {
           delete object[fieldName];
@@ -48,7 +48,7 @@
   }
 
   function convertQuadSuffixedTypesToQuads(object) {
-    tv.b.iterObjectFieldsRecursively(
+    tr.b.iterObjectFieldsRecursively(
         object,
         function(object, fieldName, fieldValue) {
         });
@@ -98,8 +98,8 @@
     }
 
     if (hasRecursed &&
-        (object instanceof tv.c.trace_model.ObjectSnapshot ||
-         object instanceof tv.c.trace_model.ObjectInstance))
+        (object instanceof tr.model.ObjectSnapshot ||
+         object instanceof tr.model.ObjectInstance))
       return;
 
     for (var key in object) {
@@ -111,11 +111,11 @@
         key = newKey;
       }
 
-      // Convert objects with keys ending with Quad to tv.b.Quad type.
-      if (/Quad$/.test(key) && !(object[key] instanceof tv.b.Quad)) {
+      // Convert objects with keys ending with Quad to tr.b.Quad type.
+      if (/Quad$/.test(key) && !(object[key] instanceof tr.b.Quad)) {
         var q;
         try {
-          q = tv.b.Quad.from8Array(object[key]);
+          q = tr.b.Quad.from8Array(object[key]);
         } catch (e) {
           console.log(e);
         }
@@ -123,11 +123,11 @@
         continue;
       }
 
-      // Convert objects with keys ending with Rect to tv.b.Rect type.
-      if (/Rect$/.test(key) && !(object[key] instanceof tv.b.Rect)) {
+      // Convert objects with keys ending with Rect to tr.b.Rect type.
+      if (/Rect$/.test(key) && !(object[key] instanceof tr.b.Rect)) {
         var r;
         try {
-          r = tv.b.Rect.fromArray(object[key]);
+          r = tr.b.Rect.fromArray(object[key]);
         } catch (e) {
           console.log(e);
         }
diff --git a/trace-viewer/trace_viewer/extras/chrome/cc/util_test.html b/trace-viewer/trace_viewer/extras/chrome/cc/util_test.html
index 76a08d3..57a51ce 100644
--- a/trace-viewer/trace_viewer/extras/chrome/cc/util_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/cc/util_test.html
@@ -13,13 +13,13 @@
 
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('nameConvert', function() {
-    assert.equal(tv.e.cc.convertNameToJSConvention('_foo'), '_foo');
-    assert.equal(tv.e.cc.convertNameToJSConvention('foo_'), 'foo_');
-    assert.equal(tv.e.cc.convertNameToJSConvention('foo'), 'foo');
-    assert.equal(tv.e.cc.convertNameToJSConvention('foo_bar'), 'fooBar');
-    assert.equal(tv.e.cc.convertNameToJSConvention('foo_bar_baz'),
+    assert.equal(tr.e.cc.convertNameToJSConvention('_foo'), '_foo');
+    assert.equal(tr.e.cc.convertNameToJSConvention('foo_'), 'foo_');
+    assert.equal(tr.e.cc.convertNameToJSConvention('foo'), 'foo');
+    assert.equal(tr.e.cc.convertNameToJSConvention('foo_bar'), 'fooBar');
+    assert.equal(tr.e.cc.convertNameToJSConvention('foo_bar_baz'),
                  'fooBarBaz');
   });
 
@@ -40,7 +40,7 @@
         }
       }
     };
-    tv.e.cc.preInitializeObject(object);
+    tr.e.cc.preInitializeObject(object);
     assert.deepEqual(object, expected);
   });
 
@@ -59,7 +59,7 @@
         {fooBar: 8}
       ]
     };
-    tv.e.cc.preInitializeObject(object);
+    tr.e.cc.preInitializeObject(object);
     assert.deepEqual(object, expected);
   });
 
@@ -69,8 +69,8 @@
         some_quad: [1, 2, 3, 4, 5, 6, 7, 8]
       }
     };
-    tv.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.someQuad, tv.b.Quad);
+    tr.e.cc.preInitializeObject(object);
+    assert.instanceOf(object.args.someQuad, tr.b.Quad);
   });
 
   test('quadConversionNested', function() {
@@ -82,9 +82,9 @@
         non_nested_quad: [1, 2, 3, 4, 5, 6, 7, 8]
       }
     };
-    tv.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.nestedField.aQuad, tv.b.Quad);
-    assert.instanceOf(object.args.nonNestedQuad, tv.b.Quad);
+    tr.e.cc.preInitializeObject(object);
+    assert.instanceOf(object.args.nestedField.aQuad, tr.b.Quad);
+    assert.instanceOf(object.args.nonNestedQuad, tr.b.Quad);
   });
 
   test('rectCoversion', function() {
@@ -93,8 +93,8 @@
         some_rect: [1, 2, 3, 4]
       }
     };
-    tv.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.someRect, tv.b.Rect);
+    tr.e.cc.preInitializeObject(object);
+    assert.instanceOf(object.args.someRect, tr.b.Rect);
   });
 
   test('rectCoversionNested', function() {
@@ -106,9 +106,9 @@
         non_nested_rect: [1, 2, 3, 4]
       }
     };
-    tv.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.nestedField.aRect, tv.b.Rect);
-    assert.instanceOf(object.args.nonNestedRect, tv.b.Rect);
+    tr.e.cc.preInitializeObject(object);
+    assert.instanceOf(object.args.nestedField.aRect, tr.b.Rect);
+    assert.instanceOf(object.args.nonNestedRect, tr.b.Rect);
   });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_auditor.html b/trace-viewer/trace_viewer/extras/chrome/chrome_auditor.html
index 5e8a286..4bd637b 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_auditor.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_auditor.html
@@ -6,8 +6,8 @@
 -->
 <link rel="import" href="/base/base.html">
 <link rel="import" href="/core/auditor.html">
-<link rel="import" href="/core/trace_model/event_info.html">
-<link rel="import" href="/extras/audits/utils.html">
+<link rel="import" href="/model/event_info.html">
+<link rel="import" href="/base/range_utils.html">
 <link rel="import" href="/extras/chrome/chrome_model_helper.html">
 <link rel="import" href="/extras/rail/rail_ir_finder.html">
 
@@ -17,8 +17,8 @@
 /**
  * @fileoverview Base class for trace data Auditors.
  */
-tv.exportTo('tv.e.audits', function() {
-  var Auditor = tv.c.Auditor;
+tr.exportTo('tr.e.audits', function() {
+  var Auditor = tr.c.Auditor;
 
   /**
    * Auditor for Chrome-specific traces.
@@ -26,11 +26,11 @@
    */
   function ChromeAuditor(model) {
     this.model = model;
-    if (tv.e.audits.ChromeModelHelper.supportsModel(this.model)) {
-      var modelHelper = new tv.e.audits.ChromeModelHelper(this.model);
+    if (tr.e.audits.ChromeModelHelper.supportsModel(this.model)) {
+      var modelHelper = new tr.e.audits.ChromeModelHelper(this.model);
 
-      // Must be a browser in order to do audits.
-      if (modelHelper.browser === undefined)
+      // Must be a browserHelper in order to do audits.
+      if (modelHelper.browserHelper === undefined)
         this.modelHelper = undefined;
       else
         this.modelHelper = modelHelper;
@@ -63,8 +63,8 @@
       if (window.profilingView)
         return;
 
-      if (tv.e.audits.RAILIRFinder.supportsModelHelper(this.modelHelper)) {
-        var rirf = new tv.e.audits.RAILIRFinder(this.model, this.modelHelper);
+      if (tr.e.rail.RAILIRFinder.supportsModelHelper(this.modelHelper)) {
+        var rirf = new tr.e.rail.RAILIRFinder(this.model, this.modelHelper);
         rirf.findAllInteractionRecords().forEach(function(ir) {
           this.model.addInteractionRecord(ir);
         }.bind(this));
@@ -75,18 +75,18 @@
 
     addBigTaskAlerts: function() {
       var model = this.model;
-      tv.b.iterItems(this.modelHelper.renderers, function(pid, renderer) {
+      tr.b.iterItems(this.modelHelper.rendererHelpers, function(pid, renderer) {
         var slices = renderer.mainThread.sliceGroup.slices;
         slices.forEach(function(slice) {
           if (slice.category != 'toplevel')
             return;
           if (slice.duration > 75.0) {
-            var alertInfo = new tv.c.trace_model.EventInfo(
+            var alertInfo = new tr.model.EventInfo(
                 'Task too long',
-                'Tasks taking >= 75ms are bad, and should be broken up to' +
+                'Tasks taking >= 75ms are bad, and should be broken up to ' +
                 'ensure the main thread is responsive');
             var center = slice.start + 0.5 * slice.duration;
-            var alert = new tv.c.trace_model.Alert(
+            var alert = new tr.model.Alert(
                 alertInfo, center, [slice]);
             model.alerts.push(alert);
           }
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_auditor_test.html b/trace-viewer/trace_viewer/extras/chrome/chrome_auditor_test.html
index 29fa188..25d3991 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_auditor_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_auditor_test.html
@@ -7,15 +7,15 @@
 
 <link rel="import" href="/base/ui/color_scheme.html">
 <link rel="import" href="/extras/chrome/chrome_auditor.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/test_utils.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function createModelWithChromeAuditor(customizeModelCallback) {
-    return tv.c.test_utils.newModelWithAuditor(function(m) {
+    return tr.c.test_utils.newModelWithAuditor(function(m) {
       m.browserProcess = m.getOrCreateProcess(1);
       m.browserMain = m.browserProcess.getOrCreateThread(2);
       m.browserMain.name = 'CrBrowserMain';
@@ -28,22 +28,22 @@
       m.renderer1Compositor.name = 'Compositor';
 
       customizeModelCallback(m);
-    }, tv.e.audits.ChromeAuditor);
+    }, tr.e.audits.ChromeAuditor);
   }
 
   function newInputLatencyEvent(tsStart, tsEnd, opt_args) {
-    var e = new tv.c.trace_model.AsyncSlice(
+    var e = new tr.model.AsyncSlice(
         'benchmark', 'InputLatency',
-        tv.b.ui.getColorIdForGeneralPurposeString('InputLatency'),
+        tr.b.ui.getColorIdForGeneralPurposeString('InputLatency'),
         tsStart, opt_args);
     e.duration = tsEnd - tsStart;
     return e;
   }
 
   function newImplRenderingStatsEvent(ts, opt_args) {
-    var e = new tv.c.trace_model.ThreadSlice(
+    var e = new tr.model.ThreadSlice(
         'benchmark', 'BenchmarkInstrumentation::ImplThreadRenderingStats',
-        tv.b.ui.getColorIdForGeneralPurposeString('x'),
+        tr.b.ui.getColorIdForGeneralPurposeString('x'),
         ts, opt_args, 0);
     return e;
   }
@@ -59,15 +59,15 @@
       bAsyncSlices.push(newInputLatencyEvent(183, 216));
 
       var rm1Slices = m.renderer1Compositor.sliceGroup;
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(113));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(130));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(147));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(163));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(180));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(197));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(213));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(230));
-      rm1Slices.pushSlices(newImplRenderingStatsEvent(247));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(113));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(130));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(147));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(163));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(180));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(197));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(213));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(230));
+      rm1Slices.pushSlice(newImplRenderingStatsEvent(247));
     });
 
   });
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper.html b/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper.html
index 06c1b80..d8703cf 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper.html
@@ -14,9 +14,9 @@
 /**
  * @fileoverview Utilities for accessing trace data about the Chrome browser.
  */
-tv.exportTo('tv.e.audits', function() {
+tr.exportTo('tr.e.audits', function() {
   function ChromeBrowserHelper(modelHelper, process) {
-    tv.e.audits.ChromeProcessHelper.call(this, modelHelper, process);
+    tr.e.audits.ChromeProcessHelper.call(this, modelHelper, process);
     this.mainThread_ = process.findAtMostOneThreadNamed('CrBrowserMain');
   }
 
@@ -27,10 +27,10 @@
   };
 
   ChromeBrowserHelper.prototype = {
-    __proto__: tv.e.audits.ChromeProcessHelper.prototype,
+    __proto__: tr.e.audits.ChromeProcessHelper.prototype,
 
-    get rendererProcesses() {
-      return this.modelHelper.rendererProcesses;
+    get rendererHelpers() {
+      return this.modelHelper.rendererHelpers;
     },
 
     getLoadingEventsInRange: function(rangeOfInterest) {
@@ -53,7 +53,7 @@
         thread.iterateAllEvents(function(event) {
           if (!event.isTopLevel)
             return;
-          if (!(event instanceof tv.e.cc.InputLatencyAsyncSlice))
+          if (!(event instanceof tr.e.cc.InputLatencyAsyncSlice))
             return;
           hasLatency = true;
         });
@@ -103,14 +103,16 @@
     },
 
     iterAllThreads: function(func, opt_this) {
-      tv.b.iterItems(this.process.threads, function(tid, thread) {
+      tr.b.iterItems(this.process.threads, function(tid, thread) {
         func.call(opt_this, thread);
       });
-      this.rendererProcesses.forEach(function(rendererProcess) {
-        tv.b.iterItems(rendererProcess.threads, function(tid, thread) {
+
+      tr.b.iterItems(this.rendererHelpers, function(pid, rendererHelper) {
+        var rendererProcess = rendererHelper.process;
+        tr.b.iterItems(rendererProcess.threads, function(tid, thread) {
           func.call(opt_this, thread);
         });
-      });
+      }, this);
     }
   };
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper_test.html b/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper_test.html
index 08cfbcb..59ce031 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_browser_helper_test.html
@@ -10,50 +10,51 @@
 <link rel="import" href="/extras/chrome/chrome_test_utils.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var audits = tv.e.audits;
+tr.b.unittest.testSuite(function() {
+  var audits = tr.e.audits;
 
   function getRange(min, max) {
-    var range = new tv.b.Range();
+    var range = new tr.b.Range();
     range.min = min;
     range.max = max;
     return range;
   }
 
   test('LoadingEvent', function() {
-    var model = tv.e.audits.newChromeModel(function() { });
-    var modelHelper = new tv.e.audits.ChromeModelHelper(model);
+    var model = tr.e.audits.newChromeModel(function() { });
+    var modelHelper = new tr.e.audits.ChromeModelHelper(model);
     audits.addLoadingEvent(model, {start: 1, end: 10});
-    assert.equal(1, modelHelper.browser.getLoadingEventsInRange(
+    assert.equal(1, modelHelper.browserHelper.getLoadingEventsInRange(
       getRange(0, 100)).length);
   });
 
   test('ProvisionalLoadEvent', function() {
-    var model = tv.e.audits.newChromeModel(function() { });
-    var modelHelper = new tv.e.audits.ChromeModelHelper(model);
+    var model = tr.e.audits.newChromeModel(function() { });
+    var modelHelper = new tr.e.audits.ChromeModelHelper(model);
     audits.addProvisionalLoadEvent(model, {start: 1, end: 10});
-    assert.equal(1, modelHelper.browser.getCommitProvisionalLoadEventsInRange(
-      getRange(0, 100)).length);
+    assert.equal(1,
+      modelHelper.browserHelper.getCommitProvisionalLoadEventsInRange(
+        getRange(0, 100)).length);
   });
 
   test('LatencyEvent', function() {
-    var model = tv.e.audits.newChromeModel(function() { });
-    var modelHelper = new tv.e.audits.ChromeModelHelper(model);
+    var model = tr.e.audits.newChromeModel(function() { });
+    var modelHelper = new tr.e.audits.ChromeModelHelper(model);
     audits.addGeneralLatencyInfoEvent(model, {start: 1, end: 10});
-    assert.equal(1, modelHelper.browser.getLatencyEventsInRange(
+    assert.equal(1, modelHelper.browserHelper.getLatencyEventsInRange(
       getRange(0, 100)).length);
   });
 
   test('NetworkEvent', function() {
-    var model = tv.e.audits.newChromeModel(function() { });
-    var modelHelper = new tv.e.audits.ChromeModelHelper(model);
+    var model = tr.e.audits.newChromeModel(function() { });
+    var modelHelper = new tr.e.audits.ChromeModelHelper(model);
     audits.addNetworkEvent(model, {start: 1, end: 10});
-    assert.equal(1, modelHelper.browser.getAllNetworkEventsInRange(
+    assert.equal(1, modelHelper.browserHelper.getAllNetworkEventsInRange(
       getRange(0, 100)).length);
   });
 });
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper.html b/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper.html
index d898fb4..a16f605 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper.html
@@ -15,11 +15,11 @@
 /**
  * @fileoverview Utilities for accessing trace data about the Chrome browser.
  */
-tv.exportTo('tv.e.audits', function() {
+tr.exportTo('tr.e.audits', function() {
   function findChromeBrowserProcess(model) {
     var browserProcesses = [];
     model.getAllProcesses().forEach(function(process) {
-      if (!tv.e.audits.ChromeBrowserHelper.isBrowserProcess(process))
+      if (!tr.e.audits.ChromeBrowserHelper.isBrowserProcess(process))
         return;
       browserProcesses.push(process);
     }, this);
@@ -33,7 +33,7 @@
   function findChromeRenderProcesses(model) {
     var rendererProcesses = [];
     model.getAllProcesses().forEach(function(process) {
-      if (!tv.e.audits.ChromeRendererHelper.isRenderProcess(process))
+      if (!tr.e.audits.ChromeRendererHelper.isRenderProcess(process))
         return;
       rendererProcesses.push(process);
     });
@@ -46,22 +46,23 @@
   function ChromeModelHelper(model) {
     this.model_ = model;
 
-    // Find browser.
+    // Find browserHelper.
     this.browserProcess_ = findChromeBrowserProcess(model);
     if (this.browserProcess_) {
-      this.browser_ = new tv.e.audits.ChromeBrowserHelper(
+      this.browserHelper_ = new tr.e.audits.ChromeBrowserHelper(
           this, this.browserProcess_);
     } else {
-      this.browser_ = undefined;
+      this.browserHelper_ = undefined;
     }
 
-    // Find renderers.
-    this.rendererProcesses_ = findChromeRenderProcesses(model);
+    // Find rendererHelpers.
+    var rendererProcesses_ = findChromeRenderProcesses(model);
 
-    this.renderers_ = {};
-    this.rendererProcesses_.forEach(function(renderProcess) {
-      var renderer = new tv.e.audits.ChromeRendererHelper(this, renderProcess);
-      this.renderers_[renderer.pid] = renderer;
+    this.rendererHelpers_ = {};
+    rendererProcesses_.forEach(function(renderProcess) {
+      var rendererHelper = new tr.e.audits.ChromeRendererHelper(
+        this, renderProcess);
+      this.rendererHelpers_[rendererHelper.pid] = rendererHelper;
     }, this);
   }
 
@@ -90,16 +91,12 @@
       return this.browserProcess_;
     },
 
-    get browser() {
-      return this.browser_;
+    get browserHelper() {
+      return this.browserHelper_;
     },
 
-    get rendererProcesses() {
-      return this.rendererProcesses_;
-    },
-
-    get renderers() {
-      return this.renderers_;
+    get rendererHelpers() {
+      return this.rendererHelpers_;
     }
   };
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper_test.html b/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper_test.html
index a9fed10..83c6ae1 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_model_helper_test.html
@@ -9,16 +9,16 @@
 <link rel="import" href="/extras/chrome/chrome_test_utils.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newAsyncSliceEx = tv.c.test_utils.newAsyncSliceEx;
+tr.b.unittest.testSuite(function() {
+  var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx;
 
   test('getLatencyData', function() {
-    var m = tv.e.audits.newChromeModel(function(m) {
+    var m = tr.e.audits.newChromeModel(function(m) {
       m.browserMain.asyncSliceGroup.push(newAsyncSliceEx({
         title: 'InputLatency::GestureScrollUpdate',
         cat: 'benchmark',
@@ -35,8 +35,9 @@
       }));
     });
 
-    var modelHelper = new tv.e.audits.ChromeModelHelper(m);
-    var latencyEvents = modelHelper.browser.getLatencyEventsInRange(m.bounds);
+    var modelHelper = new tr.e.audits.ChromeModelHelper(m);
+    var latencyEvents = modelHelper.browserHelper.getLatencyEventsInRange(
+      m.bounds);
     assert.equal(latencyEvents.length, 1);
   });
 
@@ -80,50 +81,50 @@
       frame_ts += 16000 + 1000 * (i % 2);
     }
 
-    var m = new tv.c.TraceModel(events);
-    var modelHelper = new tv.e.audits.ChromeModelHelper(m);
+    var m = new tr.Model(events);
+    var modelHelper = new tr.e.audits.ChromeModelHelper(m);
 
     // Testing browser impl and main rendering stats.
-    var frameEvents = modelHelper.browser.getFrameEventsInRange(
-        tv.e.audits.IMPL_FRAMETIME_TYPE, m.bounds);
-    var frametimeData = tv.e.audits.getFrametimeDataFromEvents(frameEvents);
+    var frameEvents = modelHelper.browserHelper.getFrameEventsInRange(
+        tr.e.audits.IMPL_FRAMETIME_TYPE, m.bounds);
+    var frametimeData = tr.e.audits.getFrametimeDataFromEvents(frameEvents);
     assert.equal(frametimeData.length, 9);
     for (var i = 0; i < frametimeData.length; i++) {
       assert.equal(frametimeData[i].frametime, 16 + i % 2);
     }
     // No main rendering stats.
-    frameEvents = modelHelper.browser.getFrameEventsInRange(
-        tv.e.audits.MAIN_FRAMETIME_TYPE, m.bounds);
+    frameEvents = modelHelper.browserHelper.getFrameEventsInRange(
+        tr.e.audits.MAIN_FRAMETIME_TYPE, m.bounds);
     assert.equal(frameEvents.length, 0);
 
 
     // Testing renderer 3508 impl and main rendering stats.
-    frameEvents = modelHelper.renderers[3508].getFrameEventsInRange(
-        tv.e.audits.MAIN_FRAMETIME_TYPE, m.bounds);
-    frametimeData = tv.e.audits.getFrametimeDataFromEvents(frameEvents);
+    frameEvents = modelHelper.rendererHelpers[3508].getFrameEventsInRange(
+        tr.e.audits.MAIN_FRAMETIME_TYPE, m.bounds);
+    frametimeData = tr.e.audits.getFrametimeDataFromEvents(frameEvents);
     assert.equal(frametimeData.length, 9);
     for (var i = 0; i < frametimeData.length; i++) {
       assert.equal(frametimeData[i].frametime, 16 + i % 2);
     }
 
     // No impl rendering stats.
-    frameEvents = modelHelper.renderers[3508].getFrameEventsInRange(
-        tv.e.audits.IMPL_FRAMETIME_TYPE, m.bounds);
+    frameEvents = modelHelper.rendererHelpers[3508].getFrameEventsInRange(
+        tr.e.audits.IMPL_FRAMETIME_TYPE, m.bounds);
     assert.equal(frameEvents.length, 0);
 
 
     // Testing renderer 3509 impl and main rendering stats.
-    frameEvents = modelHelper.renderers[3509].getFrameEventsInRange(
-        tv.e.audits.IMPL_FRAMETIME_TYPE, m.bounds);
-    frametimeData = tv.e.audits.getFrametimeDataFromEvents(frameEvents);
+    frameEvents = modelHelper.rendererHelpers[3509].getFrameEventsInRange(
+        tr.e.audits.IMPL_FRAMETIME_TYPE, m.bounds);
+    frametimeData = tr.e.audits.getFrametimeDataFromEvents(frameEvents);
     assert.equal(frametimeData.length, 9);
     for (var i = 0; i < frametimeData.length; i++) {
       assert.equal(frametimeData[i].frametime, 16 + i % 2);
     }
 
-    frameEvents = modelHelper.renderers[3509].getFrameEventsInRange(
-        tv.e.audits.MAIN_FRAMETIME_TYPE, m.bounds);
-    frametimeData = tv.e.audits.getFrametimeDataFromEvents(frameEvents);
+    frameEvents = modelHelper.rendererHelpers[3509].getFrameEventsInRange(
+        tr.e.audits.MAIN_FRAMETIME_TYPE, m.bounds);
+    frametimeData = tr.e.audits.getFrametimeDataFromEvents(frameEvents);
     assert.equal(frametimeData.length, 9);
     for (var i = 0; i < frametimeData.length; i++) {
       assert.equal(frametimeData[i].frametime, 16 + i % 2);
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_process_helper.html b/trace-viewer/trace_viewer/extras/chrome/chrome_process_helper.html
index 5fdecb8..4654389 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_process_helper.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_process_helper.html
@@ -12,7 +12,7 @@
 /**
  * @fileoverview Utilities for accessing trace data about the Chrome browser.
  */
-tv.exportTo('tv.e.audits', function() {
+tr.exportTo('tr.e.audits', function() {
   var MAIN_FRAMETIME_TYPE = 'main_frametime_type';
   var IMPL_FRAMETIME_TYPE = 'impl_frametime_type';
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_renderer_helper.html b/trace-viewer/trace_viewer/extras/chrome/chrome_renderer_helper.html
index dbd67f0..c660a62 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_renderer_helper.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_renderer_helper.html
@@ -12,9 +12,9 @@
 /**
  * @fileoverview Utilities for accessing trace data about the Chrome browser.
  */
-tv.exportTo('tv.e.audits', function() {
+tr.exportTo('tr.e.audits', function() {
   function ChromeRendererHelper(modelHelper, process) {
-    tv.e.audits.ChromeProcessHelper.call(this, modelHelper, process);
+    tr.e.audits.ChromeProcessHelper.call(this, modelHelper, process);
     this.mainThread_ = process.findAtMostOneThreadNamed('CrRendererMain');
     this.compositorThread_ = process.findAtMostOneThreadNamed('Compositor');
     this.rasterWorkerThreads_ = process.findAllThreadsMatching(function(t) {
@@ -37,7 +37,7 @@
   };
 
   ChromeRendererHelper.prototype = {
-    __proto__: tv.e.audits.ChromeProcessHelper.prototype,
+    __proto__: tr.e.audits.ChromeProcessHelper.prototype,
 
     get mainThread() {
       return this.mainThread_;
diff --git a/trace-viewer/trace_viewer/extras/chrome/chrome_test_utils.html b/trace-viewer/trace_viewer/extras/chrome/chrome_test_utils.html
index dedeaaf..871d642 100644
--- a/trace-viewer/trace_viewer/extras/chrome/chrome_test_utils.html
+++ b/trace-viewer/trace_viewer/extras/chrome/chrome_test_utils.html
@@ -5,9 +5,9 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/extras/chrome/chrome_process_helper.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
@@ -15,9 +15,9 @@
 /**
  * @fileoverview Base class for trace data Auditors.
  */
-tv.exportTo('tv.e.audits', function() {
+tr.exportTo('tr.e.audits', function() {
   function newChromeModel(customizeModelCallback) {
-    return tv.c.test_utils.newModel(function(model) {
+    return tr.c.test_utils.newModel(function(model) {
       model.browserProcess = model.getOrCreateProcess(1);
       model.browserMain = model.browserProcess.getOrCreateThread(2);
       model.browserMain.name = 'CrBrowserMain';
@@ -39,7 +39,7 @@
   function addGeneralLatencyInfoEvent(model, dict) {
     dict.title = 'InputLatency';
     dict.isTopLevel = true;
-    var slice = tv.c.test_utils.newAsyncSliceEx(dict);
+    var slice = tr.c.test_utils.newAsyncSliceEx(dict);
     model.rendererMain.asyncSliceGroup.push(slice);
     return slice;
   }
@@ -50,7 +50,7 @@
     dict.start = dict.flingStart;
     dict.end = topEvent.end;
     dict.title = 'InputLatency:GestureFlingStart';
-    var flingStartEvent = tv.c.test_utils.newAsyncSliceEx(dict);
+    var flingStartEvent = tr.c.test_utils.newAsyncSliceEx(dict);
     topEvent.subSlices.push(flingStartEvent);
     return topEvent;
   }
@@ -61,36 +61,35 @@
     dict.start = dict.flingCancel;
     dict.end = topEvent.end;
     dict.title = 'InputLatency:GestureFlingCancel';
-    var flingCancelEvent = tv.c.test_utils.newAsyncSliceEx(dict);
+    var flingCancelEvent = tr.c.test_utils.newAsyncSliceEx(dict);
     topEvent.subSlices.push(flingCancelEvent);
     return topEvent;
   }
 
   function addFlingAnimationEvent(model, dict) {
     dict.title = 'InputHandlerProxy::HandleGestureFling::started';
-    var slice = tv.c.test_utils.newAsyncSliceEx(dict);
+    var slice = tr.c.test_utils.newAsyncSliceEx(dict);
     model.rendererCompositor.asyncSliceGroup.push(slice);
     return slice;
   }
 
   function addFrameEvent(model, dict) {
-    dict.title = tv.e.audits.IMPL_RENDERING_STATS;
-    var slice = tv.c.test_utils.newAsyncSliceEx(dict);
+    dict.title = tr.e.audits.IMPL_RENDERING_STATS;
+    var slice = tr.c.test_utils.newAsyncSliceEx(dict);
     model.rendererMain.asyncSliceGroup.push(slice);
-    slice.parentThread = model.rendererMain;
     return slice;
   }
 
   function addLoadingEvent(model, dict) {
     dict.title = 'WebContentsImpl Loading';
-    var slice = tv.c.test_utils.newAsyncSliceEx(dict);
+    var slice = tr.c.test_utils.newAsyncSliceEx(dict);
     model.rendererMain.asyncSliceGroup.push(slice);
     return slice;
   }
 
   function addNetworkEvent(model, dict) {
     dict.title = 'Generic Network event';
-    var slice = tv.c.test_utils.newAsyncSliceEx(dict);
+    var slice = tr.c.test_utils.newAsyncSliceEx(dict);
     model.browserMain.asyncSliceGroup.push(slice);
     // TODO Why can't this be dict.cat?
     slice.cat = 'netlog';
@@ -99,9 +98,8 @@
 
   function addProvisionalLoadEvent(model, dict) {
     dict.title = 'RenderFrameImpl::didCommitProvisionalLoad';
-    var slice = tv.c.test_utils.newAsyncSliceEx(dict);
+    var slice = tr.c.test_utils.newAsyncSliceEx(dict);
     model.rendererMain.asyncSliceGroup.push(slice);
-    slice.parentThread = model.rendererMain;
     return slice;
   }
 
diff --git a/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice.html b/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice.html
index 29b712b..9e81226 100644
--- a/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice.html
+++ b/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice.html
@@ -4,27 +4,16 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/core/trace_model/async_slice.html">
+<link rel="import" href="/model/async_slice.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.gpu', function() {
-  var AsyncSlice = tv.c.trace_model.AsyncSlice;
-  var ChannelColors = new Object();
-  var ChannelColorID = 1;
+tr.exportTo('tr.e.gpu', function() {
+  var AsyncSlice = tr.model.AsyncSlice;
 
   function GpuAsyncSlice() {
     AsyncSlice.apply(this, arguments);
-
-    // Have service and device channels match color IDs.
-    if (this.args.channel) {
-      var channel = this.args.channel;
-      if (!ChannelColors[channel]) {
-        ChannelColors[channel] = ChannelColorID++;
-      }
-      this.colorId = ChannelColors[channel];
-    }
   }
 
   GpuAsyncSlice.prototype = {
diff --git a/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice_test.html b/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice_test.html
index 6e6e25e..e41741c 100644
--- a/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/gpu/gpu_async_slice_test.html
@@ -6,14 +6,15 @@
 -->
 
 <link rel="import" href="/extras/chrome/gpu/gpu.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
+<link rel="import" href="/model/model.html">
+
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var AsyncSlice = tv.c.trace_model.AsyncSlice;
-  var GpuAsyncSlice = tv.e.gpu.GpuAsyncSlice;
+tr.b.unittest.testSuite(function() {
+  var AsyncSlice = tr.model.AsyncSlice;
+  var GpuAsyncSlice = tr.e.gpu.GpuAsyncSlice;
 
   test('construct', function() {
     assert.equal(AsyncSlice.getConstructor('disabled-by-default-gpu.device',
@@ -35,21 +36,6 @@
     assert.equal(s_service.viewSubGroupTitle, 'Service.test_channel2');
   });
 
-  test('color', function() {
-    var s1 = new GpuAsyncSlice('disabled-by-default-gpu.device', 'gpu1',
-                               7, 0, {'channel': 'test_channel1'});
-
-    var s2 = new GpuAsyncSlice('disabled-by-default-gpu.service', 'gpu2',
-                               7, 0, {'channel': 'test_channel2'});
-
-    var s3 = new GpuAsyncSlice('disabled-by-default-gpu.service', 'gpu2',
-                               7, 0, {'channel': 'test_channel1'});
-
-    assert.notEqual(s1.colorId, s2.colorId);
-    assert.notEqual(s2.colorId, s3.colorId);
-    assert.equal(s1.colorId, s3.colorId);
-  });
-
   test('import', function() {
     var events = [
       {name: 'trace1', args: {}, pid: 1, ts: 100,
@@ -65,7 +51,7 @@
       {name: 'trace3', args: {'channel': 'test_channel'}, pid: 1, ts: 200,
        cat: 'disabled-by-default-gpu.device', tid: 2, ph: 'e', id: 73}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
     assert.equal(t2.asyncSliceGroup.length, 3);
 
@@ -77,8 +63,6 @@
     assert.instanceOf(slice2, GpuAsyncSlice);
     assert.instanceOf(slice3, GpuAsyncSlice);
 
-    assert.equal(slice2.colorId, slice3.colorId);
-
     assert.equal(slice1.viewSubGroupTitle, 'trace1');
     assert.equal(slice2.viewSubGroupTitle, 'Service.test_channel');
     assert.equal(slice3.viewSubGroupTitle, 'Device.test_channel');
diff --git a/trace-viewer/trace_viewer/extras/chrome/gpu/state.html b/trace-viewer/trace_viewer/extras/chrome/gpu/state.html
index e32555c..1c1a79d 100644
--- a/trace-viewer/trace_viewer/extras/chrome/gpu/state.html
+++ b/trace-viewer/trace_viewer/extras/chrome/gpu/state.html
@@ -6,13 +6,13 @@
 -->
 
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.gpu', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.gpu', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * @constructor
diff --git a/trace-viewer/trace_viewer/extras/chrome/gpu/state_test.html b/trace-viewer/trace_viewer/extras/chrome/gpu/state_test.html
index 11eb941..657211b 100644
--- a/trace-viewer/trace_viewer/extras/chrome/gpu/state_test.html
+++ b/trace-viewer/trace_viewer/extras/chrome/gpu/state_test.html
@@ -7,22 +7,22 @@
 
 <link rel="import" href="/extras/chrome/gpu/gpu.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script src="/extras/chrome/gpu/state_test_data.js"></script>
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
-    var m = new tv.c.TraceModel(g_gpu_state_trace);
-    var p = tv.b.dictionaryValues(m.processes)[0];
+    var m = new tr.Model(g_gpu_state_trace);
+    var p = tr.b.dictionaryValues(m.processes)[0];
 
     var instance = p.objects.getAllInstancesNamed('gpu::State')[0];
     var snapshot = instance.snapshots[0];
 
-    assert.instanceOf(snapshot, tv.e.gpu.StateSnapshot);
+    assert.instanceOf(snapshot, tr.e.gpu.StateSnapshot);
     assert.typeOf(snapshot.screenshot, 'string');
     instance.wasDeleted(150);
   });
diff --git a/trace-viewer/trace_viewer/extras/chrome/gpu/state_view.html b/trace-viewer/trace_viewer/extras/chrome/gpu/state_view.html
index af2758e..55c6184 100644
--- a/trace-viewer/trace_viewer/extras/chrome/gpu/state_view.html
+++ b/trace-viewer/trace_viewer/extras/chrome/gpu/state_view.html
@@ -7,22 +7,22 @@
 
 <link rel="stylesheet" href="/extras/chrome/gpu/state_view.css">
 <link rel="import" href="/core/analysis/object_snapshot_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.gpu', function() {
+tr.exportTo('tr.e.gpu', function() {
   /*
    * Displays a GPU state snapshot in a human readable form.
    * @constructor
    */
-  var StateSnapshotView = tv.b.ui.define(
+  var StateSnapshotView = tr.b.ui.define(
       'gpu-state-snapshot-view',
-      tv.c.analysis.ObjectSnapshotView);
+      tr.c.analysis.ObjectSnapshotView);
 
   StateSnapshotView.prototype = {
-    __proto__: tv.c.analysis.ObjectSnapshotView.prototype,
+    __proto__: tr.c.analysis.ObjectSnapshotView.prototype,
 
     decorate: function() {
       this.classList.add('gpu-state-snapshot-view');
@@ -37,7 +37,7 @@
       }
     }
   };
-  tv.c.analysis.ObjectSnapshotView.register(
+  tr.c.analysis.ObjectSnapshotView.register(
     StateSnapshotView,
     {typeName: 'gpu::State'});
 
diff --git a/trace-viewer/trace_viewer/extras/chrome_config.html b/trace-viewer/trace_viewer/extras/chrome_config.html
index 92697bc..bb8c46d 100644
--- a/trace-viewer/trace_viewer/extras/chrome_config.html
+++ b/trace-viewer/trace_viewer/extras/chrome_config.html
@@ -34,12 +34,15 @@
 <link rel="import" href="/extras/chrome/gpu/gpu.html">
 
 <!-- Side panels are chrome-only for now -->
-<link rel="import" href="/extras/side_panel/input_latency.html">
-<link rel="import" href="/extras/side_panel/time_summary.html">
+<link rel="import" href="/extras/side_panel/input_latency_side_panel.html">
+<link rel="import" href="/extras/side_panel/time_summary_side_panel.html">
 
 <!-- Sample analysis is chrome-only because it brings in D3 which is HUGE -->
 <link rel="import" href="/extras/analysis/sampling_summary.html">
 
 <!-- Auditors are fun -->
 <link rel="import" href="/extras/chrome/chrome_auditor.html">
-<link rel="import" href="/extras/audits/android_auditor.html">
+<link rel="import" href="/extras/android/android_auditor.html">
+
+<!-- RAIL is fun too -->
+<link rel="import" href="/extras/rail/rail_score_side_panel.html">
diff --git a/trace-viewer/trace_viewer/extras/deep_reports/html_results.html b/trace-viewer/trace_viewer/extras/deep_reports/html_results.html
index 3603203..5709f3c 100644
--- a/trace-viewer/trace_viewer/extras/deep_reports/html_results.html
+++ b/trace-viewer/trace_viewer/extras/deep_reports/html_results.html
@@ -5,20 +5,20 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 <!--
 This class tries to (simply) copy the telemetry Results object, but outputs
 directly to an HTML table. It takes things that look like Telemetry values,
 and updates the table internally.
 -->
-<polymer-element name="tv-e-dr-html-results">
+<polymer-element name="tr-e-dr-html-results">
   <template>
     <style>
     :host {
       display: flex;
     }
     </style>
-    <tracing-analysis-nested-table id="table"></tracing-analysis-nested-table>
+    <tr-b-ui-table id="table"></tr-b-ui-table>
   </template>
   <script>
   'use strict';
diff --git a/trace-viewer/trace_viewer/extras/deep_reports/main.html b/trace-viewer/trace_viewer/extras/deep_reports/main.html
index cb788f6..e57613c 100644
--- a/trace-viewer/trace_viewer/extras/deep_reports/main.html
+++ b/trace-viewer/trace_viewer/extras/deep_reports/main.html
@@ -14,7 +14,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.deep_reports', function() {
+tr.exportTo('tr.e.deep_reports', function() {
   /**
    * Runs deep reports on the provided files, and pushes telemetry-style
    * values to the results object.
@@ -28,7 +28,7 @@
         url: filename
       };
       lastP = lastP.then(function() {
-        return loadTraceModelFromFileAsync(filename);
+        return loadModelFromFileAsync(filename);
       });
       lastP = lastP.then(function(model) {
         processModel(results, page, model);
@@ -37,13 +37,13 @@
     return lastP;
   }
 
-  function loadTraceModelFromFileAsync(filename) {
-    return tv.b.getAsync(filename).then(function(trace) {
-      var io = new tv.c.ImportOptions();
+  function loadModelFromFileAsync(filename) {
+    return tr.b.getAsync(filename).then(function(trace) {
+      var io = new tr.ImportOptions();
       io.shiftWorldToZero = true;
       io.pruneEmptyContainers = false;
 
-      var m = new tv.c.TraceModel();
+      var m = new tr.Model();
       try {
         m.importTraces([trace], io);
       } catch (e) {
@@ -57,18 +57,18 @@
     /* TODO(nduca): Need eakeufner's Telemetry value system here so we can
      * be smart in aggregating results.
     */
-    results.addValue(tv.e.deep_reports.ScalarValue.fromDict(page, {
+    results.addValue(tr.e.deep_reports.ScalarValue.fromDict(page, {
       type: 'scalar',
       name: 'numProcesses', units: 'processes', important: true,
       value: model.numProcesses
     }));
 
-    tv.e.deep_reports.RAILDeepReporter.addResultsForModel(results, page, model);
+    tr.e.deep_reports.RAILDeepReporter.addResultsForModel(results, page, model);
 
-    if (tv.e.audits.ChromeModelHelper.supportsModel(model)) {
-      var helper = new tv.e.audits.ChromeModelHelper(model);
+    if (tr.e.audits.ChromeModelHelper.supportsModel(model)) {
+      var helper = new tr.e.audits.ChromeModelHelper(model);
       if (false) {
-        var latencyEvents = helper.browser.getLatencyEventsInRange(
+        var latencyEvents = helper.browserHelper.getLatencyEventsInRange(
           model.bounds);
         window.allTitles = window.allTitles || {};
         latencyEvents.forEach(function(event) {
diff --git a/trace-viewer/trace_viewer/extras/deep_reports/rail_deep_reporter.html b/trace-viewer/trace_viewer/extras/deep_reports/rail_deep_reporter.html
index eadb6d7..2a2f65d 100644
--- a/trace-viewer/trace_viewer/extras/deep_reports/rail_deep_reporter.html
+++ b/trace-viewer/trace_viewer/extras/deep_reports/rail_deep_reporter.html
@@ -15,7 +15,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.deep_reports', function() {
+tr.exportTo('tr.e.deep_reports', function() {
 
   function RAILDeepReporter() {
   };
@@ -23,29 +23,29 @@
   RAILDeepReporter.addResultsForModel = function(results, page, model) {
     var rirs = [];
     model.interaction_records.forEach(function(ir) {
-      if (ir instanceof tv.e.audits.RAILInteractionRecord)
+      if (ir instanceof tr.e.rail.RAILInteractionRecord)
         rirs.push(ir);
     });
 
     if (rirs.length === 0)
       return;
 
-    var railScore = tv.e.audits.RAILScore.compute(rirs);
+    var railScore = tr.e.rail.RAILScore.compute(rirs);
 
     results.addValue(
-        new tv.e.deep_reports.ScalarValue(
+        new tr.e.deep_reports.ScalarValue(
             page, 'numRailIRs', 'ms', rirs.length));
 
-    tv.b.iterItems(railScore, function(key, value) {
+    tr.b.iterItems(railScore, function(key, value) {
       if (key === 'score')
         return;
       results.addValue(
-        new tv.e.deep_reports.ScalarValue(
+        new tr.e.deep_reports.ScalarValue(
           page, key, 'rails', value));
     });
 
     results.addValue(
-      new tv.e.deep_reports.ScalarValue(
+      new tr.e.deep_reports.ScalarValue(
         page, 'railScore', 'rails', railScore.score));
   }
 
diff --git a/trace-viewer/trace_viewer/extras/deep_reports/scalar_value.html b/trace-viewer/trace_viewer/extras/deep_reports/scalar_value.html
index d2f005d..e622e66 100644
--- a/trace-viewer/trace_viewer/extras/deep_reports/scalar_value.html
+++ b/trace-viewer/trace_viewer/extras/deep_reports/scalar_value.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.deep_reports', function() {
+tr.exportTo('tr.e.deep_reports', function() {
   function ScalarValue(page, name, units, value,
                        opt_important, opt_description) {
     this.type = 'scalar';
@@ -38,4 +38,4 @@
     ScalarValue: ScalarValue
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/extras/drive/side_panel_comments.html b/trace-viewer/trace_viewer/extras/drive/comments_side_panel.html
similarity index 89%
rename from trace-viewer/trace_viewer/extras/drive/side_panel_comments.html
rename to trace-viewer/trace_viewer/extras/drive/comments_side_panel.html
index a260816..f58ae65 100644
--- a/trace-viewer/trace_viewer/extras/drive/side_panel_comments.html
+++ b/trace-viewer/trace_viewer/extras/drive/comments_side_panel.html
@@ -7,8 +7,8 @@
 
 <link rel="import" href="/extras/drive/comment_element.html">
 
-<polymer-element name='tv-e-analysis-side-panel-comments'
-    extends='tv-c-side-panel'>
+<polymer-element name='tr-e-d-comments-side-panel'
+    extends='tr-c-side-panel'>
   <template>
     <style>
     :host {
@@ -57,7 +57,7 @@
 
   Polymer({
     ready: function() {
-      this.rangeOfInterest_ = new tv.b.Range();
+      this.rangeOfInterest_ = new tr.b.Range();
       this.selection_ = undefined;
       this.comments_ = [];
       this.annotationFromComment_ = undefined;
@@ -70,7 +70,7 @@
 
     attached: function() {
       if (this.commentProvider_ === undefined)
-        this.commentProvider_ = new tv.e.analysis.DefaultCommentProvider();
+        this.commentProvider_ = new tr.e.analysis.DefaultCommentProvider();
       this.commentProvider_.attachToElement(this);
     },
 
@@ -83,10 +83,10 @@
       if (anchor === undefined)
         return;
 
-      var uiState = JSON.parse(anchor).a[0][tv.e.drive.constants.ANCHOR_NAME];
+      var uiState = JSON.parse(anchor).a[0][tr.e.drive.constants.ANCHOR_NAME];
 
       var myEvent = new CustomEvent('navigateToUIState', { detail:
-          new tv.c.UIState(new tv.c.Location(uiState.location.xWorld,
+          new tr.c.UIState(new tr.c.Location(uiState.location.xWorld,
                                              uiState.location.yComponents),
                                              uiState.scaleX)
           });
@@ -94,13 +94,13 @@
 
       if (this.annotationFromComment_)
         this.model.removeAnnotation(this.annotationFromComment_);
-      var loc = new tv.c.Location(uiState.location.xWorld,
+      var loc = new tr.c.Location(uiState.location.xWorld,
                                   uiState.location.yComponents);
 
       var text = sender.comment.author.displayName + ': ' +
           sender.comment.content;
       this.annotationFromComment_ =
-          new tv.c.trace_model.CommentBoxAnnotation(loc, text);
+          new tr.model.CommentBoxAnnotation(loc, text);
       this.model.addAnnotation(this.annotationFromComment_);
     },
 
@@ -171,7 +171,9 @@
       };
     },
 
-    textLabel: 'Comments'
+    get textLabel() {
+      return 'Comments';
+    }
   });
 
   </script>
diff --git a/trace-viewer/trace_viewer/extras/drive/side_panel_comments_test.html b/trace-viewer/trace_viewer/extras/drive/comments_side_panel_test.html
similarity index 91%
rename from trace-viewer/trace_viewer/extras/drive/side_panel_comments_test.html
rename to trace-viewer/trace_viewer/extras/drive/comments_side_panel_test.html
index 3b62dc6..1a4fa5f 100644
--- a/trace-viewer/trace_viewer/extras/drive/side_panel_comments_test.html
+++ b/trace-viewer/trace_viewer/extras/drive/comments_side_panel_test.html
@@ -5,13 +5,13 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/extras/drive/side_panel_comments.html">
+<link rel="import" href="/extras/drive/comments_side_panel.html">
 <link rel="import" href="/core/test_utils.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   function StubCommentProvider() {
     this.addDummyComment('Lorem ipsum dolor sit amet');
     this.addDummyComment('consectetur adipiscing elit');
@@ -63,7 +63,7 @@
   };
 
   test('instantiate', function() {
-    var panel = document.createElement('tv-e-analysis-side-panel-comments');
+    var panel = document.createElement('tr-e-d-comments-side-panel');
     panel.setCommentProvider(new StubCommentProvider);
     this.addHTMLOutput(panel);
   });
diff --git a/trace-viewer/trace_viewer/extras/drive/drive_comment_provider.html b/trace-viewer/trace_viewer/extras/drive/drive_comment_provider.html
index 6266bd5..6e13c79 100644
--- a/trace-viewer/trace_viewer/extras/drive/drive_comment_provider.html
+++ b/trace-viewer/trace_viewer/extras/drive/drive_comment_provider.html
@@ -6,9 +6,9 @@
 -->
 
 <link rel="import" href="/core/side_panel/side_panel.html">
-<link rel="import" href="/core/trace_model/comment_box_annotation.html">
+<link rel="import" href="/model/comment_box_annotation.html">
 
-<link rel="import" href="/extras/drive/side_panel_comments.html">
+<link rel="import" href="/extras/drive/comments_side_panel.html">
 
 <script>
 'use strict';
@@ -17,12 +17,12 @@
   function addDriveCommentWithUIState_(text, uiState) {
     gapi.client.load('drive', 'v2', function() {
       var request = gapi.client.drive.revisions.get({
-        'fileId': tv.e.drive.getDriveFileId(),
+        'fileId': tr.e.drive.getDriveFileId(),
         'revisionId': 'head'
       });
       request.execute(function(resp) {
         var anchorObject = {};
-        anchorObject[tv.e.drive.constants.ANCHOR_NAME] = uiState;
+        anchorObject[tr.e.drive.constants.ANCHOR_NAME] = uiState;
         var anchor = {
           'r': resp.id,
           'a': [anchorObject]
@@ -30,7 +30,7 @@
         anchor = JSON.stringify(anchor);
         gapi.client.load('drive', 'v2', function() {
           var request = gapi.client.drive.comments.insert({
-            'fileId': tv.e.drive.getDriveFileId(),
+            'fileId': tr.e.drive.getDriveFileId(),
             'resource': {'content': text, 'anchor': anchor}
           });
           request.execute();
@@ -47,7 +47,7 @@
                             onCommentWithUIState.bind(this));
 }());
 
-tv.exportTo('tv.e.analysis', function() {
+tr.exportTo('tr.e.analysis', function() {
   function DefaultCommentProvider() { }
 
   DefaultCommentProvider.prototype = {
@@ -71,7 +71,7 @@
       var self = this;
       gapi.client.load('drive', 'v2', function() {
         var request = gapi.client.drive.comments.list({
-          'fileId': tv.e.drive.getDriveFileId()
+          'fileId': tr.e.drive.getDriveFileId()
         });
         request.execute(function(results) {
           self.attachedElement_.comments_ = results.items;
@@ -83,7 +83,7 @@
       var self = this;
       gapi.client.load('drive', 'v2', function() {
         var request = gapi.client.drive.comments.insert({
-          'fileId': tv.e.drive.getDriveFileId(),
+          'fileId': tr.e.drive.getDriveFileId(),
           'resource': {'content': body}
         });
         request.execute(function(resp) {
diff --git a/trace-viewer/trace_viewer/extras/drive/index.html b/trace-viewer/trace_viewer/extras/drive/index.html
index 6432a85..5cc4ded 100644
--- a/trace-viewer/trace_viewer/extras/drive/index.html
+++ b/trace-viewer/trace_viewer/extras/drive/index.html
@@ -146,7 +146,7 @@
 
   (function() {
 
-    tv.exportTo('tv.e.drive', function() {
+    tr.exportTo('tr.e.drive', function() {
       var appId = '239864068844';
       var constants = {
         APP_ID: appId,
@@ -209,8 +209,8 @@
 
     function onAuthApiLoad(tryImmediate, resultCallback) {
       window.gapi.auth.authorize(
-          {'client_id': tv.e.drive.constants.CLIENT_ID,
-              'scope': tv.e.drive.constants.SCOPE, 'immediate': tryImmediate},
+          {'client_id': tr.e.drive.constants.CLIENT_ID,
+              'scope': tr.e.drive.constants.SCOPE, 'immediate': tryImmediate},
           function(authResult) {
             handleAuthResult(authResult, tryImmediate, resultCallback);
           });
@@ -245,11 +245,11 @@
         var picker = new google.picker.PickerBuilder()
                        .enableFeature(google.picker.Feature.NAV_HIDDEN)
                        .enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
-                       .setAppId(tv.e.drive.constants.APP_ID)
+                       .setAppId(tr.e.drive.constants.APP_ID)
                        .setOAuthToken(oauthToken_)
                        .addView(view)
                        .addView(new google.picker.DocsUploadView())
-                       .setDeveloperKey(tv.e.drive.constants.DEVELOPER_KEY)
+                       .setDeveloperKey(tr.e.drive.constants.DEVELOPER_KEY)
                        .setCallback(pickerCallback)
                        .build();
         picker.setVisible(true);
@@ -264,7 +264,7 @@
 
     function initShareButton() {
       shareClient_ = new gapi.drive.share.ShareClient(
-          tv.e.drive.constants.APP_ID);
+          tr.e.drive.constants.APP_ID);
       shareClient_.setItemIds([driveFileId_]);
     }
 
@@ -279,7 +279,7 @@
 
     function downloadFile(file) {
       if (file.downloadUrl) {
-        var downloadingOverlay = tv.b.ui.Overlay();
+        var downloadingOverlay = tr.b.ui.Overlay();
         downloadingOverlay.title = 'Downloading...';
         downloadingOverlay.userCanClose = false;
         downloadingOverlay.msgEl = document.createElement('div');
@@ -328,22 +328,22 @@
         imageList.push({'image': img, 'name': user.displayName});
       }
       for (i = 0; i < imageList.length; i++) {
-        var collabTooltip = tv.b.ui.createDiv({
+        var collabTooltip = tr.b.ui.createDiv({
             className: 'collaborator-tooltip'
         });
-        var collabTooltipContent = tv.b.ui.createDiv({
+        var collabTooltipContent = tr.b.ui.createDiv({
             className: 'collaborator-tooltip-content'
         });
         collabTooltipContent.textContent = imageList[i].name;
         collabTooltip.appendChild(collabTooltipContent);
         collabspan.appendChild(collabTooltip);
-        var collabTooltipArrow = tv.b.ui.createDiv({
+        var collabTooltipArrow = tr.b.ui.createDiv({
             className: 'collaborator-tooltip-arrow'});
         collabTooltip.appendChild(collabTooltipArrow);
-        var collabTooltipArrowBefore = tv.b.ui.createDiv({
+        var collabTooltipArrowBefore = tr.b.ui.createDiv({
             className: 'collaborator-tooltip-arrow-before'});
         collabTooltipArrow.appendChild(collabTooltipArrowBefore);
-        var collabTooltipArrowAfter = tv.b.ui.createDiv({
+        var collabTooltipArrowAfter = tr.b.ui.createDiv({
             className: 'collaborator-tooltip-arrow-after'});
         collabTooltipArrow.appendChild(collabTooltipArrowAfter);
 
@@ -398,7 +398,7 @@
     }
 
     function createViewFromTraces(filenames, traces) {
-      var m = new tv.c.TraceModel();
+      var m = new tr.Model();
       var p = m.importTracesWithProgressDialog(traces, true);
       p.then(
           function() {
@@ -410,9 +410,9 @@
             timelineViewEl_.viewTitle = '';
           },
           function(err) {
-            var downloadingOverlay = new tv.b.ui.Overlay();
+            var downloadingOverlay = new tr.b.ui.Overlay();
             downloadingOverlay.textContent =
-                tv.b.normalizeException(err).message;
+                tr.b.normalizeException(err).message;
             downloadingOverlay.title = 'Import error';
             downloadingOverlay.visible = true;
           });
@@ -434,7 +434,7 @@
       timelineViewEl_ = document.querySelector('x-timeline-view');
       var navbar = document.getElementById('navbar');
       timelineViewEl_.style.top = navbar.offsetHeight + 'px';
-      tv.b.ui.decorate(timelineViewEl_, tv.c.TimelineView);
+      tr.b.ui.decorate(timelineViewEl_, tr.c.TimelineView);
     }
 
     window.addEventListener('load', onLoad);
diff --git a/trace-viewer/trace_viewer/extras/full_config.html b/trace-viewer/trace_viewer/extras/full_config.html
index cb7b716..256f6d5 100644
--- a/trace-viewer/trace_viewer/extras/full_config.html
+++ b/trace-viewer/trace_viewer/extras/full_config.html
@@ -8,4 +8,4 @@
 <!-- The full config is all the configs slammed together. -->
 <link rel="import" href="/extras/chrome_config.html">
 <link rel="import" href="/extras/systrace_config.html">
-<link rel="import" href="/extras/lean_config.html">
\ No newline at end of file
+<link rel="import" href="/extras/lean_config.html">
diff --git a/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter.html b/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter.html
index d3d7f56..b4c4776 100644
--- a/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter.html
+++ b/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter.html
@@ -8,7 +8,7 @@
 <link rel="import" href="/core/tracks/highlighter.html">
 <link rel="import" href="/core/timeline_track_view.html">
 <link rel="import" href="/core/timeline_viewport.html">
-<link rel="import" href="/core/tracks/trace_model_track.html">
+<link rel="import" href="/core/tracks/model_track.html">
 
 <script>
 'use strict';
@@ -16,9 +16,9 @@
 /**
  * @fileoverview Provides the VSyncHighlighter class.
  */
-tv.exportTo('tv.e.highlighter', function() {
+tr.exportTo('tr.e.highlighter', function() {
 
-  var Highlighter = tv.c.tracks.Highlighter;
+  var Highlighter = tr.c.tracks.Highlighter;
 
   /**
    * Highlights VSync events on the model track (using "zebra" striping).
@@ -122,7 +122,7 @@
     var stripes = [];
 
     // Find the lowest and highest index within the viewport.
-    var lowIndex = tv.b.findLowIndexInSortedArray(
+    var lowIndex = tr.b.findLowIndexInSortedArray(
         times,
         function(time) { return time; },
         minTime);
@@ -164,7 +164,7 @@
 
       var stripeRange = stripes[stripes.length - 1][1] - stripes[0][0];
       var stripeDensity = stripes.length / (dt.scaleX * stripeRange);
-      var clampedStripeDensity = tv.b.clamp(stripeDensity,
+      var clampedStripeDensity = tr.b.clamp(stripeDensity,
           VSyncHighlighter.VSYNC_DENSITY_OPAQUE,
           VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT);
       var opacity =
@@ -176,7 +176,7 @@
 
       var pixelRatio = window.devicePixelRatio || 1;
       var height = viewHeight * pixelRatio;
-      ctx.fillStyle = tv.b.ui.colorToRGBAString(
+      ctx.fillStyle = tr.b.ui.colorToRGBAString(
           VSyncHighlighter.VSYNC_HIGHLIGHT_COLOR,
           VSyncHighlighter.VSYNC_HIGHLIGHT_ALPHA * opacity);
 
@@ -189,7 +189,7 @@
   };
 
   // Register the highlighter.
-  tv.c.tracks.Highlighter.register(VSyncHighlighter);
+  tr.c.tracks.Highlighter.register(VSyncHighlighter);
 
   return {
     VSyncHighlighter: VSyncHighlighter
diff --git a/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter_test.html b/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter_test.html
index dc55c54..4cf5b8f 100644
--- a/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter_test.html
+++ b/trace-viewer/trace_viewer/extras/highlighter/vsync_highlighter_test.html
@@ -5,21 +5,21 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/thread.html">
+<link rel="import" href="/model/thread.html">
 <link rel="import" href="/extras/highlighter/vsync_highlighter.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
-  var VSyncHighlighter = tv.e.highlighter.VSyncHighlighter;
+  var VSyncHighlighter = tr.e.highlighter.VSyncHighlighter;
 
   var VIEW_L_WORLD = 100;
   var VIEW_R_WORLD = 1000;
 
   function buildModel(slices) {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var process = model.getOrCreateProcess(1);
     for (var i = 0; i < slices.length; i++) {
       var thread = process.getOrCreateThread(i);
@@ -31,7 +31,7 @@
   }
 
   function buildSlice(title, time) {
-    return new tv.c.trace_model.ThreadSlice('', title, 0, time, {});
+    return new tr.model.ThreadSlice('', title, 0, time, {});
   }
 
   function testFindVSyncTimes(slices, expectedTimes) {
diff --git a/trace-viewer/trace_viewer/extras/importer/battor_importer.html b/trace-viewer/trace_viewer/extras/importer/battor_importer.html
index 78a433b..c3fd297 100644
--- a/trace-viewer/trace_viewer/extras/importer/battor_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/battor_importer.html
@@ -5,21 +5,21 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 /**
  * @fileoverview Imports text files in the BattOr format into the
- * Tracemodel. This format is output by the BattOr executable.
+ * Model. This format is output by the BattOr executable.
  *
  * This importer assumes the events arrive as a string. The unit tests provide
  * examples of the trace format.
  */
 'use strict';
 
-tv.exportTo('tv.e.importer.battor', function() {
-  var Importer = tv.c.importer.Importer;
+tr.exportTo('tr.e.importer.battor', function() {
+  var Importer = tr.importer.Importer;
 
   /**
    * Imports linux perf events into a specified model.
@@ -27,18 +27,15 @@
    */
   function BattorImporter(model, events) {
     this.importPriority = 3; // runs after the linux_perf importer
-    this.series_ = undefined;
     this.sampleRate_ = undefined;
     this.model_ = model;
     this.events_ = events;
-    this.kernelThreadStates_ = {};
-    this.lines_ = [];
-    this.pseudoThreadCounter = 1;
   }
 
   var TestExports = {};
 
-  var battorLineRE = /^(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)$/;
+  var battorDataLineRE = /^(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)$/;
+  var battorHeaderLineRE = /^# BattOr/;
   var sampleRateLineRE = /^# sample_rate=(\d+)Hz/;
 
   /**
@@ -51,10 +48,7 @@
     if (!(typeof(events) === 'string' || events instanceof String))
       return false;
 
-    if (/^# BattOr/.test(events))
-      return true;
-
-    return false;
+    return battorHeaderLineRE.test(events);
   };
 
   BattorImporter.prototype = {
@@ -70,30 +64,91 @@
     importEvents: function(isSecondaryImport) {
       // Create series and import power samples into it.
       var name = 'power';
-      var series = new tv.c.trace_model.CounterSeries('value',
-          tv.b.ui.getColorIdForGeneralPurposeString(name + '.' + 'value'));
+      var series = new tr.model.CounterSeries('value',
+          tr.b.ui.getColorIdForGeneralPurposeString(name + '.' + 'value'));
       this.importPowerSamples(series);
-      this.series_ = series;
 
-      // Find the markers for the beginning and end of the vreg sync.
+      // Find the sync markers.
       var syncMarks = this.model_.getClockSyncRecordsNamed('battor');
-      if (syncMarks.length < 2) {
+      if (syncMarks.length < 1) {
         this.model_.importWarning({
           type: 'clock_sync',
-          message: 'Cannot import BattOr measurments without a sync signal.'
+          message: 'Cannot import BattOr power trace without a sync signal.'
         });
         return;
       }
 
+      // Try each of the clock sync techinques in order of their accuracy.
+      var shiftTs = this.correlationClockSync(syncMarks, series);
+
+      if (shiftTs === undefined) {
+        this.model_.importWarning({
+          type: 'clock_sync',
+          message: 'All of the BattOr power trace clock sync techinques failed.'
+        });
+        return;
+      }
+
+      // Add a counter for power to the GUI.
+      var ctr = this.model_.kernel.getOrCreateCounter(null, 'Power');
+      if (ctr.numSeries === 0) {
+        ctr.addSeries(series);
+      }
+
+      ctr.shiftTimestampsForward(shiftTs);
+    },
+
+    /**
+     * Walks the events and populates a time series with power samples.
+     */
+    importPowerSamples: function(series) {
+      var lines = this.events_.split('\n');
+
+      // Update the model's bounds.
+      this.model_.updateBounds();
+      var minTs = 0;
+      if (this.model_.bounds.min !== undefined)
+        minTs = this.model_.bounds.min;
+
+      lines.forEach(function(line) {
+        if (line.length === 0)
+          return;
+
+        if (/^#/.test(line)) {
+          // Parse sample rate.
+          groups = sampleRateLineRE.exec(line);
+          if (!groups)
+            return;
+          this.sampleRate_ = parseInt(groups[1]);
+        } else {
+          // Parse power sample.
+          var groups = battorDataLineRE.exec(line);
+          if (!groups) {
+            this.model_.importWarning({
+              type: 'parse_error',
+              message: 'Unrecognized line: ' + line
+            });
+            return;
+          }
+
+          var time = parseFloat(groups[1]) + minTs;
+          var voltage_mV = parseFloat(groups[2]);
+          var current_mA = parseFloat(groups[3]);
+          series.addCounterSample(time, (voltage_mV * current_mA) / 1000);
+        }
+      }, this);
+    },
+
+    correlationClockSync: function(syncMarks, series) {
       // Find the regulator counter for the sync.
       var syncCtr = this.model_.kernel.counters[
           'null.vreg ' + syncMarks[0].args['regulator'] + ' enabled'];
       if (syncCtr === undefined) {
         this.model_.importWarning({
           type: 'clock_sync',
-          message: 'Cannot import BattOr power trace without sync vreg.'
+          message: 'Cannot correlate BattOr power trace without sync vreg.'
         });
-        return;
+        return undefined;
       }
 
       // Store the sync events from the regulator counter.
@@ -139,7 +194,7 @@
           type: 'not_enough_samples',
           message: 'Not enough power samples to correlate with sync signal.'
         });
-        return;
+        return undefined;
       }
 
       // Cross-correlate the ground truth with the last 5s of power samples.
@@ -171,64 +226,17 @@
         }
       }
 
-      // Add a counter for power to the GUI.
-      var ctr = this.model_.kernel.getOrCreateCounter(null, 'Power');
-      if (ctr.numSeries === 0) {
-        ctr.addSeries(series);
-      }
-      this.counter_ = ctr;
-
       // Shift the time of the power samples by the recovered sync start time.
       var corrPeakTs = ((minShift + corrPeakIdx) / this.sampleRate_);
       corrPeakTs *= 1000; // sec -> msec
       var syncStartTs = firstSyncEventTs - this.model_.bounds.min;
       var shiftTs = syncStartTs - corrPeakTs;
-      this.counter_.shiftTimestampsForward(shiftTs);
-    },
 
-    /**
-     * Walks the events and populates a time series with power samples.
-     */
-    importPowerSamples: function(series) {
-      var lines = this.events_.split('\n');
-
-      // Update the model's bounds.
-      this.model_.updateBounds();
-      var minTs = 0;
-      if (this.model_.bounds.min !== undefined)
-        minTs = this.model_.bounds.min;
-
-      lines.forEach(function(line) {
-        if (line.length == 0)
-          return;
-
-        if (/^#/.test(line)) {
-          // Parse sample rate.
-          groups = sampleRateLineRE.exec(line);
-          if (!groups)
-            return;
-          this.sampleRate_ = parseInt(groups[1]);
-        } else {
-          // Parse power sample.
-          var groups = battorLineRE.exec(line);
-          if (!groups) {
-            this.model_.importWarning({
-                type: 'parse_error',
-                message: 'Unrecognized line: ' + line
-            });
-            return;
-          }
-
-          var time = parseFloat(groups[1]) + minTs;
-          var voltage_mV = parseFloat(groups[2]);
-          var current_mA = parseFloat(groups[3]);
-          series.addCounterSample(time, (voltage_mV * current_mA) / 1000);
-        }
-      }, this);
+      return shiftTs;
     }
   };
 
-  tv.c.importer.Importer.register(BattorImporter);
+  tr.importer.Importer.register(BattorImporter);
 
   return {
     BattorImporter: BattorImporter,
diff --git a/trace-viewer/trace_viewer/extras/importer/battor_importer_test.html b/trace-viewer/trace_viewer/extras/importer/battor_importer_test.html
index ebffb88..509cd38 100644
--- a/trace-viewer/trace_viewer/extras/importer/battor_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/battor_importer_test.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
   var BATTOR_LINES = [
     '# BattOr',
@@ -48,14 +48,14 @@
   ];
 
   test('canImport', function() {
-    assert.isFalse(tv.e.importer.battor.BattorImporter.canImport('string'));
-    assert.isFalse(tv.e.importer.battor.BattorImporter.canImport([]));
-    assert.isTrue(tv.e.importer.battor.BattorImporter.canImport(
+    assert.isFalse(tr.e.importer.battor.BattorImporter.canImport('string'));
+    assert.isFalse(tr.e.importer.battor.BattorImporter.canImport([]));
+    assert.isTrue(tr.e.importer.battor.BattorImporter.canImport(
         BATTOR_LINES.join('\n')));
   });
 
   test('importPowerSamplesAndTrace', function() {
-    var m = new tv.c.TraceModel(SYSTRACE_LINES.join('\n'), false);
+    var m = new tr.Model(SYSTRACE_LINES.join('\n'), false);
     m.importTraces([BATTOR_LINES.join('\n')]);
     assert.isFalse(m.hasImportWarnings);
 
@@ -72,13 +72,13 @@
   });
 
   test('importMissingLinuxTrace', function() {
-    var m = new tv.c.TraceModel(BATTOR_LINES.join('\n'), false);
+    var m = new tr.Model(BATTOR_LINES.join('\n'), false);
     assert.isTrue(m.hasImportWarnings);
   });
 
   test('importNotEnoughSamples', function() {
     var shortLines = BATTOR_LINES.slice(0, 5);
-    var m = new tv.c.TraceModel(SYSTRACE_LINES.join('\n'), false);
+    var m = new tr.Model(SYSTRACE_LINES.join('\n'), false);
     m.importTraces([shortLines.join('\n')]);
     assert.isTrue(m.hasImportWarnings);
   });
diff --git a/trace-viewer/trace_viewer/extras/importer/ddms_importer.html b/trace-viewer/trace_viewer/extras/importer/ddms_importer.html
index 1e6b4c9..637bd47 100644
--- a/trace-viewer/trace_viewer/extras/importer/ddms_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/ddms_importer.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/extras/importer/jszip.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/importer/importer.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/importer/importer.html">
 
 <script>
 /**
@@ -15,8 +15,8 @@
  */
 'use strict';
 
-tv.exportTo('tv.e.importer.ddms', function() {
-  var Importer = tv.c.importer.Importer;
+tr.exportTo('tr.e.importer.ddms', function() {
+  var Importer = tr.importer.Importer;
 
   var kPid = 0;
   var kCategory = 'java';
@@ -210,7 +210,7 @@
   };
 
   // Register the DdmsImporter to the Importer.
-  tv.c.importer.Importer.register(DdmsImporter);
+  tr.importer.Importer.register(DdmsImporter);
 
   return {
     DdmsImporter: DdmsImporter
diff --git a/trace-viewer/trace_viewer/extras/importer/ddms_importer_test.html b/trace-viewer/trace_viewer/extras/importer/ddms_importer_test.html
index 6f019cf..b71aade 100644
--- a/trace-viewer/trace_viewer/extras/importer/ddms_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/ddms_importer_test.html
@@ -11,15 +11,15 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('canImport', function() {
-    assert.isFalse(tv.e.importer.ddms.DdmsImporter.canImport('string'));
-    assert.isFalse(tv.e.importer.ddms.DdmsImporter.canImport([]));
-    assert.isTrue(tv.e.importer.ddms.DdmsImporter.canImport(TEST_DATA));
+    assert.isFalse(tr.e.importer.ddms.DdmsImporter.canImport('string'));
+    assert.isFalse(tr.e.importer.ddms.DdmsImporter.canImport([]));
+    assert.isTrue(tr.e.importer.ddms.DdmsImporter.canImport(TEST_DATA));
   });
 
   test('parseThreads', function() {
-    var m = new tv.c.TraceModel(TEST_DATA, false);
+    var m = new tr.Model(TEST_DATA, false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -31,7 +31,7 @@
   });
 
   test('parseMethods', function() {
-    var m = new tv.c.TraceModel(TEST_DATA, false);
+    var m = new tr.Model(TEST_DATA, false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.findAllThreadsNamed('Binder_1');
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/etw_importer.html b/trace-viewer/trace_viewer/extras/importer/etw/etw_importer.html
index 842018e..6a8668d 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/etw_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/etw_importer.html
@@ -8,14 +8,14 @@
 <link rel="import" href="/extras/importer/etw/eventtrace_parser.html">
 <link rel="import" href="/extras/importer/etw/process_parser.html">
 <link rel="import" href="/extras/importer/etw/thread_parser.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/importer/importer.html">
+<link rel="import" href="/importer/importer.html">
 <link rel="import" href="/base/base64.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 /**
  * @fileoverview Imports JSON file with the raw payloads from a Windows event
- * trace into the Tracemodel. This format is outputted by Chrome running
+ * trace into the Model. This format is outputted by Chrome running
  * on a Windows system.
  *
  * This importer assumes the events arrived as a JSON file and the payloads are
@@ -43,7 +43,7 @@
  * This importer uses specific parsers to decode recognized events.
  * A parser need to register the recognized event by calling
  * registerEventHandler(guid, opcode, handler). The parser is responsible to
- * decode the payload and update the TraceModel.
+ * decode the payload and update the Model.
  *
  * The payload formats are described there:
  *   http://msdn.microsoft.com/en-us/library/windows/desktop/aa364085(v=vs.85).aspx
@@ -51,8 +51,8 @@
  */
 'use strict';
 
-tv.exportTo('tv.e.importer.etw', function() {
-  var Importer = tv.c.importer.Importer;
+tr.exportTo('tr.e.importer.etw', function() {
+  var Importer = tr.importer.Importer;
 
   // GUID and opcode of a Thread DCStart event, as defined at the link above.
   var kThreadGuid = '3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';
@@ -70,11 +70,11 @@
     __proto__: Object.prototype,
 
     reset: function(base64_payload) {
-      var decoded_size = tv.b.Base64.getDecodedBufferLength(base64_payload);
+      var decoded_size = tr.b.Base64.getDecodedBufferLength(base64_payload);
       if (decoded_size > this.payload_.byteLength)
         this.payload_ = new DataView(new ArrayBuffer(decoded_size));
 
-      tv.b.Base64.DecodeToTypedArray(base64_payload, this.payload_);
+      tr.b.Base64.DecodeToTypedArray(base64_payload, this.payload_);
       this.position_ = 0;
     },
 
@@ -275,7 +275,7 @@
     this.tidsToPid_ = {};
 
     // Instantiate the parsers; this will register handlers for known events.
-    var allTypeInfos = tv.e.importer.etw.Parser.getAllRegisteredTypeInfos();
+    var allTypeInfos = tr.e.importer.etw.Parser.getAllRegisteredTypeInfos();
     this.parsers_ = allTypeInfos.map(
         function(typeInfo) {
           return new typeInfo.constructor(this);
@@ -380,7 +380,7 @@
           event.hasOwnProperty('payload') &&
           event.guid === kThreadGuid &&
           event.op == kThreadDCStartOpcode) {
-        var decoded_size = tv.b.Base64.getDecodedBufferLength(event.payload);
+        var decoded_size = tr.b.Base64.getDecodedBufferLength(event.payload);
 
         if (event.ver == 1) {
           if (decoded_size >= 52)
@@ -466,7 +466,7 @@
   };
 
   // Register the EtwImporter to the Importer.
-  tv.c.importer.Importer.register(EtwImporter);
+  tr.importer.Importer.register(EtwImporter);
 
   return {
     EtwImporter: EtwImporter
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/etw_importer_test.html b/trace-viewer/trace_viewer/extras/importer/etw/etw_importer_test.html
index b82c208..f251471 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/etw_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/etw_importer_test.html
@@ -11,24 +11,24 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('canImport', function() {
-    assert.isFalse(tv.e.importer.etw.EtwImporter.canImport('string'));
-    assert.isFalse(tv.e.importer.etw.EtwImporter.canImport([]));
+    assert.isFalse(tr.e.importer.etw.EtwImporter.canImport('string'));
+    assert.isFalse(tr.e.importer.etw.EtwImporter.canImport([]));
 
     // Must not parse an invalid name.
     var dummy = { name: 'dummy', content: [] };
-    assert.isFalse(tv.e.importer.etw.EtwImporter.canImport(dummy));
+    assert.isFalse(tr.e.importer.etw.EtwImporter.canImport(dummy));
 
     // Must parse  an empty valid trace.
     var valid = { name: 'ETW', content: [] };
-    assert.isTrue(tv.e.importer.etw.EtwImporter.canImport(valid));
+    assert.isTrue(tr.e.importer.etw.EtwImporter.canImport(valid));
   });
 
   test('getModel', function() {
     var model = 'dummy';
     var events = [];
-    var importer = new tv.e.importer.etw.EtwImporter(model, events);
+    var importer = new tr.e.importer.etw.EtwImporter(model, events);
     assert.strictEqual(importer.model, model);
   });
 
@@ -36,7 +36,7 @@
     // Create a dummy EtwImporter.
     var model = 'dummy';
     var events = ['events'];
-    var importer = new tv.e.importer.etw.EtwImporter(model, events);
+    var importer = new tr.e.importer.etw.EtwImporter(model, events);
     var dummy_handler = function() {};
 
     // The handler must not exists.
@@ -55,7 +55,7 @@
   test('parseEvent', function() {
     var model = 'dummy';
     var events = [];
-    var importer = new tv.e.importer.etw.EtwImporter(model, events);
+    var importer = new tr.e.importer.etw.EtwImporter(model, events);
     var handler_called = false;
     var dummy_handler = function() { handler_called = true; return true; };
 
@@ -76,7 +76,7 @@
   });
 
   test('resetTooSmall', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
 
     var oldByteLength = decoder.payload_.byteLength;
@@ -97,7 +97,7 @@
   test('decode', function() {
     var model = 'dummy';
     var events = [];
-    var importer = new tv.e.importer.etw.EtwImporter(model, events);
+    var importer = new tr.e.importer.etw.EtwImporter(model, events);
 
     var decoder = importer.decoder_;
 
@@ -156,7 +156,7 @@
   });
 
   test('decodeUInteger', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
 
     decoder.reset('AQIDBAUGBwg=');
@@ -167,7 +167,7 @@
   });
 
   test('decodeString', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
 
     decoder.reset('dGVzdAA=');
@@ -178,14 +178,14 @@
   });
 
   test('decodeW16String', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
     decoder.reset('dABlAHMAdAAAAA==');
     assert.strictEqual(decoder.decodeW16String(), 'test');
   });
 
   test('decodeFixedW16String', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
     decoder.reset('dABlAHMAdAAAAA==');
     assert.strictEqual(decoder.decodeFixedW16String(32), 'test');
@@ -197,7 +197,7 @@
   });
 
   test('decodeBytes', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
     decoder.reset('AAECAwQFBgc=');
     var bytes = decoder.decodeBytes(8);
@@ -206,7 +206,7 @@
   });
 
   test('decodeSID', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
 
     // Decode a SID structure with 64-bit pointer.
@@ -220,7 +220,7 @@
   });
 
   test('decodeSystemTime', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
 
     // Decode a SystemTime structure.
@@ -237,7 +237,7 @@
   });
 
   test('decodeTimeZoneInformation', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
 
     // Decode a TimeZoneInformation structure.
@@ -258,7 +258,7 @@
   test('manageThreads', function() {
     var events = [];
     var model = 'dummy';
-    var importer = new tv.e.importer.etw.EtwImporter(model, events);
+    var importer = new tr.e.importer.etw.EtwImporter(model, events);
 
     // After initialisation, no threads must exists.
     assert.equal(Object.getOwnPropertyNames(importer.tidsToPid_).length, 0);
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser.html b/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser.html
index d023c9c..954fe16 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser.html
@@ -14,8 +14,8 @@
  * @fileoverview Parses EventTrace events in the Windows event trace format.
  */
 
-tv.exportTo('tv.e.importer.etw', function() {
-  var Parser = tv.e.importer.etw.Parser;
+tr.exportTo('tr.e.importer.etw', function() {
+  var Parser = tr.e.importer.etw.Parser;
 
   // Constants for EventTrace events.
   var guid = '68FDD900-4A3E-11D1-84F4-0000F80464E3';
@@ -94,7 +94,7 @@
 
     decodeHeader: function(header, decoder) {
       var fields = this.decodeFields(header, decoder);
-      // TODO(etienneb): Update the TraceModel with |fields|.
+      // TODO(etienneb): Update the Model with |fields|.
       return true;
     }
 
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser_test.html b/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser_test.html
index ec31a9d..c0e8a9c 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/eventtrace_parser_test.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   // Constants for EventTrace events.
   var guid = '68FDD900-4A3E-11D1-84F4-0000F80464E3';
   var kEventTraceHeaderOpcode = 0;
@@ -39,9 +39,9 @@
 
   test('DecodeFields', function() {
 
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
-    var parser = new tv.e.importer.etw.EventTraceParser(importer);
+    var parser = new tr.e.importer.etw.EventTraceParser(importer);
     var header;
     var fields;
 
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/parser.html b/trace-viewer/trace_viewer/extras/importer/etw/parser.html
index 626b58a..6ac6735 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/parser.html
@@ -20,7 +20,7 @@
  * and their constructor must register their event handlers with the
  * importer.  For example,
  *
- * var Parser = tv.e.importer.etw.Parser;
+ * var Parser = tr.e.importer.etw.Parser;
  *
  * function ThreadParser(importer) {
  *   Parser.call(this, importer);
@@ -47,7 +47,7 @@
  * true.
  *
  */
-tv.exportTo('tv.e.importer.etw', function() {
+tr.exportTo('tr.e.importer.etw', function() {
   /**
    * Parses Windows ETW events.
    * @constructor
@@ -61,9 +61,9 @@
     __proto__: Object.prototype
   };
 
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
   options.mandatoryBaseClass = Parser;
-  tv.b.decorateExtensionRegistry(Parser, options);
+  tr.b.decorateExtensionRegistry(Parser, options);
 
 
   return {
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/process_parser.html b/trace-viewer/trace_viewer/extras/importer/etw/process_parser.html
index cd489a2..3f6dc32 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/process_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/process_parser.html
@@ -24,8 +24,8 @@
  *
  * See http://msdn.microsoft.com/library/windows/desktop/aa364092.aspx
  */
-tv.exportTo('tv.e.importer.etw', function() {
-  var Parser = tv.e.importer.etw.Parser;
+tr.exportTo('tr.e.importer.etw', function() {
+  var Parser = tr.e.importer.etw.Parser;
 
   // Constants for Process events.
   var guid = '3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C';
@@ -165,7 +165,7 @@
 
     decodeDefunct: function(header, decoder) {
       var fields = this.decodeFields(header, decoder);
-      // TODO(etienneb): Update the TraceModel with |fields|.
+      // TODO(etienneb): Update the Model with |fields|.
       return true;
     }
 
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/process_parser_test.html b/trace-viewer/trace_viewer/extras/importer/etw/process_parser_test.html
index fabcf62..d6d5e78 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/process_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/process_parser_test.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   // Constants for Process events.
   var guid = '3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C';
   var kProcessStartOpcode = 1;
@@ -49,9 +49,9 @@
 
   test('DecodeFields', function() {
 
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
-    var parser = new tv.e.importer.etw.ProcessParser(importer);
+    var parser = new tr.e.importer.etw.ProcessParser(importer);
     var header;
     var fields;
 
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/thread_parser.html b/trace-viewer/trace_viewer/extras/importer/etw/thread_parser.html
index 659e5fa..ef5a749 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/thread_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/thread_parser.html
@@ -24,8 +24,8 @@
  *
  * See http://msdn.microsoft.com/library/windows/desktop/aa364132.aspx
  */
-tv.exportTo('tv.e.importer.etw', function() {
-  var Parser = tv.e.importer.etw.Parser;
+tr.exportTo('tr.e.importer.etw', function() {
+  var Parser = tr.e.importer.etw.Parser;
 
   // Constants for Thread events.
   var guid = '3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';
diff --git a/trace-viewer/trace_viewer/extras/importer/etw/thread_parser_test.html b/trace-viewer/trace_viewer/extras/importer/etw/thread_parser_test.html
index 43e018a..fc57950 100644
--- a/trace-viewer/trace_viewer/extras/importer/etw/thread_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/etw/thread_parser_test.html
@@ -12,7 +12,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
   // Constants for Thread events.
   var guid = '3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';
@@ -43,9 +43,9 @@
 
   test('DecodeFields', function() {
 
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
-    var parser = new tv.e.importer.etw.ThreadParser(importer);
+    var parser = new tr.e.importer.etw.ThreadParser(importer);
     var header;
     var fields;
 
@@ -130,9 +130,9 @@
   });
 
   test('DecodeCSwitchFields', function() {
-    var importer = new tv.e.importer.etw.EtwImporter('dummy', []);
+    var importer = new tr.e.importer.etw.EtwImporter('dummy', []);
     var decoder = importer.decoder_;
-    var parser = new tv.e.importer.etw.ThreadParser(importer);
+    var parser = new tr.e.importer.etw.ThreadParser(importer);
     var header;
     var fields;
 
diff --git a/trace-viewer/trace_viewer/extras/importer/gzip_importer.html b/trace-viewer/trace_viewer/extras/importer/gzip_importer.html
index d47b700..b3bdcb8 100644
--- a/trace-viewer/trace_viewer/extras/importer/gzip_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/gzip_importer.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/extras/importer/jszip.html">
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
@@ -16,8 +16,8 @@
  * @fileoverview GzipImporter inflates gzip compressed data and passes it along
  * to an actual importer.
  */
-tv.exportTo('tv.e.importer', function() {
-  var Importer = tv.c.importer.Importer;
+tr.exportTo('tr.e.importer', function() {
+  var Importer = tr.importer.Importer;
 
   var GZIP_MEMBER_HEADER_ID_SIZE = 3;
 
@@ -139,7 +139,7 @@
     }
   };
 
-  tv.c.importer.Importer.register(GzipImporter);
+  tr.importer.Importer.register(GzipImporter);
 
   return {
     GzipImporter: GzipImporter
diff --git a/trace-viewer/trace_viewer/extras/importer/gzip_importer_test.html b/trace-viewer/trace_viewer/extras/importer/gzip_importer_test.html
index 8af5081..f649d2c 100644
--- a/trace-viewer/trace_viewer/extras/importer/gzip_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/gzip_importer_test.html
@@ -12,8 +12,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var findSliceNamed = tv.c.test_utils.findSliceNamed;
+tr.b.unittest.testSuite(function() {
+  var findSliceNamed = tr.c.test_utils.findSliceNamed;
   var original_data =
       '[{"name":"a","args":{},"pid":52,"ts":520,"cat":"foo","tid":53,' +
       '"ph":"B"},{"name":"a","args":{},"pid":52,"ts":520,"cat":"foo",' +
@@ -24,15 +24,15 @@
       'EH+QAAAA';
 
   test('failImportEmpty', function() {
-    assert.isFalse(tv.e.importer.GzipImporter.canImport([]));
-    assert.isFalse(tv.e.importer.GzipImporter.canImport(''));
+    assert.isFalse(tr.e.importer.GzipImporter.canImport([]));
+    assert.isFalse(tr.e.importer.GzipImporter.canImport(''));
   });
 
   test('inflateString', function() {
     // Test inflating the data from a string.
     var gzip_data = atob(gzip_data_base64);
-    var importer = new tv.e.importer.GzipImporter(null, gzip_data);
-    assert.isTrue(tv.e.importer.GzipImporter.canImport(gzip_data));
+    var importer = new tr.e.importer.GzipImporter(null, gzip_data);
+    assert.isTrue(tr.e.importer.GzipImporter.canImport(gzip_data));
     assert.equal(importer.extractSubtraces()[0], original_data);
   });
 
@@ -43,16 +43,16 @@
     var view = new Uint8Array(buffer);
     for (var i = 0; i < gzip_data.length; i++)
       view[i] = gzip_data.charCodeAt(i);
-    var importer = new tv.e.importer.GzipImporter(null, buffer);
-    assert.isTrue(tv.e.importer.GzipImporter.canImport(buffer));
+    var importer = new tr.e.importer.GzipImporter(null, buffer);
+    assert.isTrue(tr.e.importer.GzipImporter.canImport(buffer));
     assert.equal(importer.extractSubtraces()[0], original_data);
   });
 
   test('import', function() {
     var gzip_data = atob(gzip_data_base64);
-    assert.isTrue(tv.e.importer.GzipImporter.canImport(gzip_data));
+    assert.isTrue(tr.e.importer.GzipImporter.canImport(gzip_data));
 
-    var model = new tv.c.TraceModel(gzip_data);
+    var model = new tr.Model(gzip_data);
     var threads = model.getAllThreads();
     assert.equal(threads.length, 1);
 
@@ -67,9 +67,9 @@
     req.overrideMimeType('text/plain; charset=x-user-defined');
     req.send(null);
     var gzip_data = req.responseText;
-    assert.isTrue(tv.e.importer.GzipImporter.canImport(gzip_data));
+    assert.isTrue(tr.e.importer.GzipImporter.canImport(gzip_data));
 
-    var model = new tv.c.TraceModel(gzip_data);
+    var model = new tr.Model(gzip_data);
     var threads = model.getAllThreads();
     assert.equal(threads.length, 2);
 
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser.html
index 6181e91..a7d3e54 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/extras/importer/linux_perf/parser.html">
-<link rel="import" href="/core/trace_model/counter_series.html">
+<link rel="import" href="/model/counter_series.html">
 
 <script>
 'use strict';
@@ -15,8 +15,8 @@
  * @fileoverview Parses trace_marker events that were inserted in the trace by
  * userland.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
-  var Parser = tv.e.importer.linux_perf.Parser;
+tr.exportTo('tr.e.importer.linux_perf', function() {
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux trace mark events that were inserted in the trace by userland.
@@ -52,11 +52,11 @@
 
     openAsyncSlice: function(thread, category, name, cookie, ts, args) {
       var asyncSliceConstructor =
-         tv.c.trace_model.AsyncSlice.getConstructor(
+         tr.model.AsyncSlice.getConstructor(
             category, name);
       var slice = new asyncSliceConstructor(
           category, name,
-          tv.b.ui.getColorIdForGeneralPurposeString(name), ts, args);
+          tr.b.ui.getColorIdForGeneralPurposeString(name), ts, args);
       var key = category + ':' + name + ':' + cookie;
       slice.id = cookie;
       slice.startThread = thread;
@@ -95,7 +95,7 @@
       slice.endThread = thread;
       slice.duration = ts - slice.start;
       slice.startThread.asyncSliceGroup.push(slice);
-      slice.subSlices = [new tv.c.trace_model.AsyncSlice(slice.category,
+      slice.subSlices = [new tr.model.AsyncSlice(slice.category,
           slice.title, slice.colorId, slice.start, slice.args, slice.duration)];
       delete this.openAsyncSlices[key];
     },
@@ -171,8 +171,8 @@
               .getOrCreateCounter(category, name);
           // Initialize the counter's series fields if needed.
           if (ctr.numSeries === 0) {
-            ctr.addSeries(new tv.c.trace_model.CounterSeries(value,
-                tv.b.ui.getColorIdForGeneralPurposeString(
+            ctr.addSeries(new tr.model.CounterSeries(value,
+                tr.b.ui.getColorIdForGeneralPurposeString(
                     ctr.name + '.' + 'value')));
           }
 
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser_test.html
index 2b343ee..595c1d7 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/android_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('androidUserlandImport', function() {
     var lines = [
       'SurfaceFlinger-4831  [001] ...1 80909.598554: tracing_mark_write: B|4829|onMessageReceived', // @suppress longLineCheck
@@ -42,7 +42,7 @@
       'SurfaceFlinger-4831  [001] ...1 80909.599087: tracing_mark_write: E',
       'SurfaceFlinger-4831  [001] ...1 80909.599104: tracing_mark_write: E'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -60,7 +60,7 @@
       'Surface Flinger -4831  [001] ...1 80909.598590: tracing_mark_write: B|4829|latchBuffer', // @suppress longLineCheck
       'Surface Flinger -4831  [001] ...1 80909.598604: tracing_mark_write: E' // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -82,7 +82,7 @@
           'tracing_mark_write: F|9649|animator:childrenOutlineAlpha|' +
           '1113053968'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -130,7 +130,7 @@
       'SurfaceFlinger-4831  [001] ...1 80909.599087: 0: E',
       'SurfaceFlinger-4831  [001] ...1 80909.599104: 0: E'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -156,7 +156,7 @@
       'SandboxedProces-2894  [000] ...1   255.663276: tracing_mark_write: F|2867|async|1113053968|arg3=3|cat1', // @suppress longLineCheck
       'SandboxedProces-2894  [000] ...1   255.663276: tracing_mark_write: trace_event_clock_sync: parent_ts=128' // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser.html
index 7e066d4..0e039e2 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/extras/importer/linux_perf/parser.html">
-<link rel="import" href="/core/trace_model/counter_series.html">
+<link rel="import" href="/model/counter_series.html">
 
 <script>
 'use strict';
@@ -15,8 +15,8 @@
  * @fileoverview Parses trace_marker events that were inserted in the trace by
  * userland.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
-  var Parser = tv.e.importer.linux_perf.Parser;
+tr.exportTo('tr.e.importer.linux_perf', function() {
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux trace mark events that were inserted in the trace by userland.
@@ -57,8 +57,8 @@
       var ctr = this.model_.kernel
               .getOrCreateCounter(null, 'bus ' + name + ' read');
       if (ctr.numSeries === 0) {
-        ctr.addSeries(new tv.c.trace_model.CounterSeries('value',
-            tv.b.ui.getColorIdForGeneralPurposeString(
+        ctr.addSeries(new tr.model.CounterSeries('value',
+            tr.b.ui.getColorIdForGeneralPurposeString(
                 ctr.name + '.' + 'value')));
       }
       ctr.series.forEach(function(series) {
@@ -68,8 +68,8 @@
       ctr = this.model_.kernel
               .getOrCreateCounter(null, 'bus ' + name + ' write');
       if (ctr.numSeries === 0) {
-        ctr.addSeries(new tv.c.trace_model.CounterSeries('value',
-            tv.b.ui.getColorIdForGeneralPurposeString(
+        ctr.addSeries(new tr.model.CounterSeries('value',
+            tr.b.ui.getColorIdForGeneralPurposeString(
                 ctr.name + '.' + 'value')));
       }
       ctr.series.forEach(function(series) {
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser_test.html
index 3652712..cfea821 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/bus_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('exynos5Bus', function() {
     var lines = [
       's3c-fb-vsync-85    [001] d..2  8116.730115: memory_bus_usage: ' +
@@ -53,7 +53,7 @@
           'cycles=6690156 ns=16725375'
 
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var counters = m.getAllCounters();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser.html
index fb619b0..68fa14c 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/extras/importer/linux_perf/parser.html">
-<link rel="import" href="/core/trace_model/counter_series.html">
+<link rel="import" href="/model/counter_series.html">
 
 <script>
 'use strict';
@@ -15,9 +15,9 @@
  * @fileoverview Parses trace_marker events that were inserted in the trace by
  * userland.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux trace mark events that were inserted in the trace by userland.
@@ -48,8 +48,8 @@
               .getOrCreateCounter(null, name);
       // Initialize the counter's series fields if needed.
       if (ctr.numSeries === 0) {
-        ctr.addSeries(new tv.c.trace_model.CounterSeries('value',
-            tv.b.ui.getColorIdForGeneralPurposeString(
+        ctr.addSeries(new tr.model.CounterSeries('value',
+            tr.b.ui.getColorIdForGeneralPurposeString(
                 ctr.name + '.' + 'value')));
       }
       ctr.series.forEach(function(series) {
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser_test.html
index 6624ea9..8314dd1 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/clock_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('clock', function() {
     var lines = [
       'cfinteractive-23    [000] d..2  8113.233768: clock_set_rate: ' +
@@ -45,7 +45,7 @@
           'fout_apll state=500000000 cpu_id=0'
     ];
 
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var counters = m.getAllCounters();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser.html
index 3fd7b98..84235e5 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses cpufreq events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux cpufreq trace events.
@@ -61,8 +61,8 @@
       // TODO(sleffler) should be per-cpu
       var kthread = this.importer.getOrCreatePseudoThread('cpufreq');
       kthread.openSlice = eventName;
-      var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-          tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+      var slice = new tr.model.Slice('', kthread.openSlice,
+          tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
           ts, args, 0);
 
       kthread.thread.sliceGroup.pushSlice(slice);
@@ -71,8 +71,8 @@
     cpufreqBoostSlice: function(ts, eventName, args) {
       var kthread = this.importer.getOrCreatePseudoThread('cpufreq_boost');
       kthread.openSlice = eventName;
-      var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-          tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+      var slice = new tr.model.Slice('', kthread.openSlice,
+          tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
           ts, args, 0);
 
       kthread.thread.sliceGroup.pushSlice(slice);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser_test.html
index 5c4cd82..c5c0b3e 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/cpufreq_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('cpuFreqTargetImport', function() {
     var lines = [
       '<idle>-0     [000] ..s3  1043.718825: cpufreq_interactive_target: ' +
@@ -19,7 +19,7 @@
       '<idle>-0     [000] ..s3  1043.718825: cpufreq_interactive_target: ' +
           'cpu=0 load=12 cur=1000000 actual=1000000 targ=200000\n'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -45,7 +45,7 @@
       '<idle>-0     [001] ..s3  1043.718832: cpufreq_interactive_notyet: ' +
           'cpu=1 load=10 cur=700000 actual=1000000 targ=200000\n'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -69,7 +69,7 @@
       'cfinteractive-23    [001] ...1  1043.719688: ' +
           'cpufreq_interactive_setspeed: cpu=0 targ=200000 actual=700000\n'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -85,7 +85,7 @@
     var lines = [
       '<idle>-0     [000] ..s3  1043.738822: cpufreq_interactive_already: cpu=0 load=18 cur=200000 actual=700000 targ=200000\n' // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -104,7 +104,7 @@
       'InputDispatcher-465   [001] ...1  1044.213948: ' +
           'cpufreq_interactive_boost: pulse\n'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -119,7 +119,7 @@
       'InputDispatcher-465   [001] ...1  1044.213948: ' +
           'cpufreq_interactive_unboost: pulse\n'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -134,7 +134,7 @@
       'kinteractive-69    [003] .... 414324.164432: ' +
           'cpufreq_interactive_up: cpu=1 targ=1400000 actual=800000'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -151,7 +151,7 @@
       'kinteractive-69    [003] .... 414365.834193: ' +
           'cpufreq_interactive_down: cpu=3 targ=800000 actual=1000000'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser.html
index e97062c..0f21983 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser.html
@@ -14,9 +14,9 @@
  * @fileoverview Parses filesystem and block device events in the Linux event
  * trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux filesystem and block device trace events.
@@ -54,11 +54,11 @@
       var kthread = this.importer.getOrCreateKernelThread(
           category + ':' + threadName, pid);
       var asyncSliceConstructor =
-         tv.c.trace_model.AsyncSlice.getConstructor(
+         tr.model.AsyncSlice.getConstructor(
             category, name);
       var slice = new asyncSliceConstructor(
           category, name,
-          tv.b.ui.getColorIdForGeneralPurposeString(name),
+          tr.b.ui.getColorIdForGeneralPurposeString(name),
           ts);
       slice.startThread = kthread.thread;
 
@@ -78,7 +78,7 @@
           slice.args = args;
           slice.endThread = kthread.thread;
           slice.subSlices = [
-            new tv.c.trace_model.AsyncSlice(category, slice.title,
+            new tr.model.AsyncSlice(category, slice.title,
                 slice.colorId, slice.start, slice.args, slice.duration)
           ];
           kthread.thread.asyncSliceGroup.push(slice);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser_test.html
index 7a09a46..c064cfb 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/disk_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('diskImport', function() {
     var lines = [
       // NB: spliced from different traces; mismatched timestamps don't matter
@@ -45,7 +45,7 @@
       'ContactsProvide-1184 [000] ...1 66.613733: f2fs_write_end: ' +
           'dev = (253,2), ino = 3342, pos = 0, len = 75, copied = 75'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var blockThread = undefined;
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser.html
index a42a6bb..480b81b 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses drm driver events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux drm trace events.
@@ -34,8 +34,8 @@
     drmVblankSlice: function(ts, eventName, args) {
       var kthread = this.importer.getOrCreatePseudoThread('drm_vblank');
       kthread.openSlice = eventName;
-      var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-          tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+      var slice = new tr.model.Slice('', kthread.openSlice,
+          tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
           ts, args, 0);
 
       kthread.thread.sliceGroup.pushSlice(slice);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser_test.html
index 1a3c147..82b4384 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/drm_parser_test.html
@@ -11,13 +11,13 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('drmImport', function() {
     var lines = [
       ' chrome-2465  [000]    71.653157: drm_vblank_event: crtc=0, seq=4233',
       ' <idle>-0     [000]    71.669851: drm_vblank_event: crtc=0, seq=4234'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser.html
index 31e1aab..7e80ca5 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses exynos events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux exynos trace events.
@@ -40,8 +40,8 @@
       var targetCpu = this.importer.getOrCreateCpu(0);
       var counter = targetCpu.getOrCreateCounter('', name);
       if (counter.numSeries === 0) {
-        counter.addSeries(new tv.c.trace_model.CounterSeries('frequency',
-            tv.b.ui.getColorIdForGeneralPurposeString(
+        counter.addSeries(new tr.model.CounterSeries('frequency',
+            tr.b.ui.getColorIdForGeneralPurposeString(
                 counter.name + '.' + 'frequency')));
       }
       counter.series.forEach(function(series) {
@@ -84,8 +84,8 @@
       var kthread = this.importer.getOrCreatePseudoThread(
           'exynos_flip_state (pipe:' + pipe + ', fb:' + fb + ')');
       if (kthread.openSlice) {
-        var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-            tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+        var slice = new tr.model.Slice('', kthread.openSlice,
+            tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
             kthread.openSliceTS,
             args,
             ts - kthread.openSliceTS);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser_test.html
index 0fe4d2a..c5d8373 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/exynos_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('exynosBusfreqImport', function() {
     var lines = [
       '     kworker/1:0-4177  [001] ....  2803.129806: ' +
@@ -23,7 +23,7 @@
       '     kworker/1:0-4177  [001] ....  2805.729039: ' +
           'exynos_busfreq_target_mif: frequency=200000'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c0 = m.kernel.cpus[0];
@@ -51,7 +51,7 @@
       '     kworker/0:1-25931 [000] .... 1000.000007: ' +
           'exynos_page_flip_state: pipe=0, fb=25, state=flipped'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
@@ -98,7 +98,7 @@
       '          <idle>-0     [000] d.h. 1000.000011: ' +
           'exynos_page_flip_state: pipe=0, fb=26, state=wait_apply'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer.html
index 29f0217..6af9f94 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer.html
@@ -5,7 +5,6 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/base/ui/color_scheme.html">
 <link rel="import" href="/extras/importer/linux_perf/bus_parser.html">
 <link rel="import" href="/extras/importer/linux_perf/clock_parser.html">
@@ -25,15 +24,14 @@
 <link rel="import" href="/extras/importer/linux_perf/workqueue_parser.html">
 <link rel="import" href="/extras/importer/linux_perf/android_parser.html">
 <link rel="import" href="/extras/importer/linux_perf/kfunc_parser.html">
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/importer/simple_line_reader.html">
-
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/importer/simple_line_reader.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 /**
  * @fileoverview Imports text files in the Linux event trace format into the
- * Tracemodel. This format is output both by sched_trace and by Linux's perf
- * tool.
+ * Model. This format is output both by sched_trace and by Linux's perf tool.
  *
  * This importer assumes the events arrive as a string. The unit tests provide
  * examples of the trace format.
@@ -46,9 +44,9 @@
  */
 'use strict';
 
-tv.exportTo('tv.e.importer.linux_perf', function() {
-  var Importer = tv.c.importer.Importer;
-  var ClockSyncRecord = tv.c.ClockSyncRecord;
+tr.exportTo('tr.e.importer.linux_perf', function() {
+  var Importer = tr.importer.Importer;
+  var ClockSyncRecord = tr.ClockSyncRecord;
 
   /**
    * Imports linux perf events into a specified model.
@@ -215,7 +213,7 @@
 
     if (/^<!DOCTYPE HTML>/.test(incoming_events) == false)
       return failure;
-    var r = new tv.c.importer.SimpleLineReader(incoming_events);
+    var r = new tr.importer.SimpleLineReader(incoming_events);
 
     // Try to find the data...
     if (!r.advanceToLineMatching(/^  <script>$/))
@@ -280,7 +278,7 @@
 
     if (/^<!DOCTYPE HTML>/.test(incoming_events) == false)
       return failure;
-    var r = new tv.c.importer.SimpleLineReader(incoming_events);
+    var r = new tr.importer.SimpleLineReader(incoming_events);
 
     // Try to find the Linux perf trace in any of the trace-data tags
     var events = [];
@@ -404,7 +402,7 @@
      * on a thread means that it is not of interest to the user.
      */
     buildPerThreadCpuSlicesFromCpuState: function() {
-      var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+      var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
 
       // Push the cpu slices to the threads that they run on.
       for (var cpuNumber in this.model_.kernel.cpus) {
@@ -462,12 +460,12 @@
             var wakeup = wakeups.shift();
             var wakeupDuration = slice.start - wakeup.ts;
             var args = {'wakeup from tid': wakeup.fromTid};
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.RUNNABLE, '',
                 wakeup.ts, args, wakeupDuration));
           }
 
-          var runningSlice = new tv.c.trace_model.ThreadTimeSlice(
+          var runningSlice = new tr.model.ThreadTimeSlice(
               thread, SCHEDULING_STATE.RUNNING, '',
               slice.start, {}, slice.duration);
           runningSlice.cpuOnWhichThreadWasRunning = slice.cpu;
@@ -492,13 +490,13 @@
             if (wakeup !== undefined) {
               midDuration = wakeup.ts - prevSlice.end;
             }
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread,
                 state, '', prevSlice.end, {}, midDuration));
             if (wakeup !== undefined) {
               var wakeupDuration = nextSlice.start - wakeup.ts;
               var args = {'wakeup from tid': wakeup.fromTid};
-              slices.push(new tv.c.trace_model.ThreadTimeSlice(
+              slices.push(new tr.model.ThreadTimeSlice(
                   thread, SCHEDULING_STATE.RUNNABLE, '',
                   wakeup.ts, args, wakeupDuration));
               wakeup = undefined;
@@ -509,37 +507,37 @@
             pushSleep(SCHEDULING_STATE.SLEEPING);
           } else if (prevSlice.args.stateWhenDescheduled == 'R' ||
                      prevSlice.args.stateWhenDescheduled == 'R+') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.RUNNABLE, '',
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 'D') {
             pushSleep(SCHEDULING_STATE.UNINTR_SLEEP);
           } else if (prevSlice.args.stateWhenDescheduled == 'T') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.STOPPED, '',
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 't') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.DEBUG, '',
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 'Z') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.ZOMBIE, '', ioWaitId,
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 'X') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.EXIT_DEAD, '',
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 'x') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.TASK_DEAD, '',
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 'K') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.WAKE_KILL, '',
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 'W') {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.WAKING, '',
                 prevSlice.end, {}, midDuration));
           } else if (prevSlice.args.stateWhenDescheduled == 'D|K') {
@@ -547,7 +545,7 @@
           } else if (prevSlice.args.stateWhenDescheduled == 'D|W') {
             pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKING);
           } else {
-            slices.push(new tv.c.trace_model.ThreadTimeSlice(
+            slices.push(new tr.model.ThreadTimeSlice(
                 thread, SCHEDULING_STATE.UNKNOWN, '',
                 prevSlice.end, {}, midDuration));
             this.model_.importWarning({
@@ -557,7 +555,7 @@
             });
           }
 
-          var runningSlice = new tv.c.trace_model.ThreadTimeSlice(
+          var runningSlice = new tr.model.ThreadTimeSlice(
               thread, SCHEDULING_STATE.RUNNING, '',
               nextSlice.start, {}, nextSlice.duration);
           runningSlice.cpuOnWhichThreadWasRunning = prevSlice.cpu;
@@ -607,7 +605,7 @@
      */
     createParsers_: function() {
       // Instantiate the parsers; this will register handlers for known events
-      var allTypeInfos = tv.e.importer.linux_perf.
+      var allTypeInfos = tr.e.importer.linux_perf.
           Parser.getAllRegisteredTypeInfos();
       var parsers = allTypeInfos.map(
           function(typeInfo) {
@@ -828,7 +826,7 @@
     }
   };
 
-  tv.c.importer.Importer.register(LinuxPerfImporter);
+  tr.importer.Importer.register(LinuxPerfImporter);
 
   return {
     LinuxPerfImporter: LinuxPerfImporter,
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer_test.html
index 7b421a4..7e69fe4 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/ftrace_importer_test.html
@@ -12,10 +12,10 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
-  var LinuxPerfImporter = tv.e.importer.linux_perf.LinuxPerfImporter;
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
+  var LinuxPerfImporter = tr.e.importer.linux_perf.LinuxPerfImporter;
   var LinuxPerfImporterTestExports =
-      tv.e.importer.linux_perf._LinuxPerfImporterTestExports;
+      tr.e.importer.linux_perf._LinuxPerfImporterTestExports;
   test('lineParserWithLegacyFmt', function() {
     var p = LinuxPerfImporterTestExports.lineParserWithLegacyFmt; // @suppress longLineCheck
     var x = p('   <idle>-0     [001]  4467.843475: sched_switch: ' +
@@ -129,7 +129,7 @@
       '#              | |       |          |         |',
       'sh-26121 [000] ...1 107464.0: tracing_mark_write: trace_event_clock_sync: name=battor regulator=8941_smbb_boost' // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var battorSyncs = m.getClockSyncRecordsNamed('battor');
@@ -235,7 +235,7 @@
           'prev_comm=kworker/u:2 prev_pid=2844 prev_prio=120 ' +
           'prev_state=S ==> next_comm=swapper next_pid=0 next_prio=120'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c = m.kernel.cpus[1];
@@ -261,7 +261,7 @@
           'prev_comm=kworker/u:2 prev_pid=2844 prev_prio=120 ' +
           'prev_state=S ==> next_comm=swapper next_pid=0 next_prio=120'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c = m.kernel.cpus[1];
@@ -276,15 +276,15 @@
     var lines = [
       ''
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'));
+    var m = new tr.Model(lines.join('\n'));
     assert.isFalse(m.hasImportWarnings);
   });
 
   test('importSystraceHtml', function() {
-    var p = tv.b.getAsync(
+    var p = tr.b.getAsync(
         '/test_data/trivial_systrace.html');
     return p.then(function(data) {
-      var m = new tv.c.TraceModel(data, false);
+      var m = new tr.Model(data, false);
       assert.isFalse(m.hasImportWarnings);
 
       assert.isDefined(m.processes[124]);
@@ -326,7 +326,7 @@
       '<\/html>'
     ];
 
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     assert.isDefined(m.processes[124]);
@@ -357,7 +357,7 @@
       '     kworker/u:2-2844  [001]  4467.843000: 0: ' +
           'trace_event_clock_sync: parent_ts=0.1'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c = m.kernel.cpus[1];
@@ -384,7 +384,7 @@
       'systrace.sh-8182  [000] 15186.203900: tracing_mark_write: ' +
           'trace_event_clock_sync: parent_ts=0'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c = m.kernel.cpus[1];
@@ -400,7 +400,7 @@
       'systrace.sh-8182  [002] ...1 2068991.686415: tracing_mark_write: E\\n\\'
     ];
 
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c = m.processes[9304].threads[8182].sliceGroup;
@@ -426,10 +426,10 @@
           'prev_pid=4404 prev_prio=120 prev_state=S ==> ' +
           'next_comm=dbus-daemon next_pid=510 next_prio=120'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
-    assert.equal(tv.b.dictionaryLength(m.kernel.cpus), 2);
+    assert.equal(tr.b.dictionaryLength(m.kernel.cpus), 2);
     assert.equal(m.kernel.bestGuessAtCpuCount, 2);
   });
 });
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser.html
index 418964a..63202bd 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses gesture events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses trace events generated by gesture library for touchpad.
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser_test.html
index 6f29209..e1de75a 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/gesture_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('gestureImport', function() {
     var lines = [
       '<...>-1837  [000] ...1 875292.741648: tracing_mark_write: ' +
@@ -99,7 +99,7 @@
       '<...>-1837  [000] ...1 875292.795231: tracing_mark_write: ' +
           'log: end: LogHardwareState'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
     var threads = m.getAllThreads();
     assert.equal(threads.length, 1);
@@ -172,7 +172,7 @@
       'X-30368 [000] ...1 1819362.482053: tracing_mark_write: ' +
           'log: end: TimerLogOutputs'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
     var threads = m.getAllThreads();
     assert.equal(threads.length, 1);
@@ -197,7 +197,7 @@
       'X-30368 [000] ...1 1819362.481988: tracing_mark_write: ' +
           'HandleTimer: end: IntegralGestureFilterInterpreter'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isTrue(m.hasImportWarnings);
     assert.equal(m.importWarnings.length, 7);
   });
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser.html
index 6cf5b3f..6393d5e 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser.html
@@ -13,8 +13,8 @@
 /**
  * @fileoverview Parses i915 driver events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
-  var Parser = tv.e.importer.linux_perf.Parser;
+tr.exportTo('tr.e.importer.linux_perf', function() {
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux i915 trace events.
@@ -85,8 +85,8 @@
     i915FlipCloseSlice: function(ts, args) {
       var kthread = this.importer.getOrCreatePseudoThread('i915_flip');
       if (kthread.openSlice) {
-        var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-            tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+        var slice = new tr.model.Slice('', kthread.openSlice,
+            tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
             kthread.openSliceTS,
             args,
             ts - kthread.openSliceTS);
@@ -99,8 +99,8 @@
     i915GemObjectSlice: function(ts, eventName, obj, args) {
       var kthread = this.importer.getOrCreatePseudoThread('i915_gem');
       kthread.openSlice = eventName + ':' + obj;
-      var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-          tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+      var slice = new tr.model.Slice('', kthread.openSlice,
+          tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
           ts, args, 0);
 
       kthread.thread.sliceGroup.pushSlice(slice);
@@ -109,8 +109,8 @@
     i915GemRingSlice: function(ts, eventName, dev, ring, args) {
       var kthread = this.importer.getOrCreatePseudoThread('i915_gem_ring');
       kthread.openSlice = eventName + ':' + dev + '.' + ring;
-      var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-          tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+      var slice = new tr.model.Slice('', kthread.openSlice,
+          tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
           ts, args, 0);
 
       kthread.thread.sliceGroup.pushSlice(slice);
@@ -119,8 +119,8 @@
     i915RegSlice: function(ts, eventName, reg, args) {
       var kthread = this.importer.getOrCreatePseudoThread('i915_reg');
       kthread.openSlice = eventName + ':' + reg;
-      var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-          tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+      var slice = new tr.model.Slice('', kthread.openSlice,
+          tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
           ts, args, 0);
 
       kthread.thread.sliceGroup.pushSlice(slice);
@@ -129,8 +129,8 @@
     i915FreqChangeSlice: function(ts, eventName, args) {
       var kthread = this.importer.getOrCreatePseudoThread('i915_gpu_freq');
       kthread.openSlice = eventName;
-      var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-          tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+      var slice = new tr.model.Slice('', kthread.openSlice,
+          tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
           ts, args, 0);
 
       kthread.thread.sliceGroup.pushSlice(slice);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser_test.html
index 50a9c65..61dc76f 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/i915_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('i915Import', function() {
     var lines = [
       // NB: spliced from different traces; mismatched timestamps don't matter
@@ -46,7 +46,7 @@
               'intel_gpu_freq_change: new_freq=350'
 
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var i915GemThread = undefined;
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser.html
index 42219a8..4e45262 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses drm driver events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux irq trace events.
@@ -79,9 +79,9 @@
 
       if (thread.lastEntryTs !== undefined) {
         var duration = ts - thread.lastEntryTs;
-        var slice = new tv.c.trace_model.Slice(
+        var slice = new tr.model.Slice(
             '', thread.irqName,
-            tv.b.ui.getColorIdForGeneralPurposeString(event[1]),
+            tr.b.ui.getColorIdForGeneralPurposeString(event[1]),
             thread.lastEntryTs, { ret: ret },
             duration);
         thread.thread.sliceGroup.pushSlice(slice);
@@ -120,9 +120,9 @@
 
       if (thread.lastEntryTs !== undefined) {
         var duration = ts - thread.lastEntryTs;
-        var slice = new tv.c.trace_model.Slice(
+        var slice = new tr.model.Slice(
             '', action,
-            tv.b.ui.getColorIdForGeneralPurposeString(event[1]),
+            tr.b.ui.getColorIdForGeneralPurposeString(event[1]),
             thread.lastEntryTs, { vec: vec },
             duration);
         thread.thread.sliceGroup.pushSlice(slice);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser_test.html
index 0f4a380..65dd6fe 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/irq_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('irqImport', function() {
     var lines = [
       ' kworker/u4:1-31907 (31907) [001] d.h3 14063.748288: ' +
@@ -23,7 +23,7 @@
       ' kworker/u4:2-31908 (31908) [000] ..s3 14063.477246: ' +
         'softirq_exit: vec=9 [action=RCU]'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser.html
index 6f24a8d..2a3a09f 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser.html
@@ -14,9 +14,9 @@
  * @fileoverview Parses graph_ent and graph_ret events that were inserted by
  * the Linux kernel's function graph trace.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var LinuxPerfParser = tv.e.importer.linux_perf.Parser;
+  var LinuxPerfParser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses graph_ent and graph_ret events that were inserted by the Linux
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser_test.html
index edf6a04..7bdbae4 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/kfunc_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('kernelFunctionParser', function() {
     var lines = [
       'Binder_2-127  ( 127) [001] ....  3431.906759: graph_ent: func=sys_write',
@@ -26,7 +26,7 @@
       'Binder_2-127  ( 127) [001] ....  3431.906896: graph_ent: func=sys_write',
       'Binder_2-127  ( 127) [001] ....  3431.906906: graph_ret: func=sys_write'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var process = m.processes[127];
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser.html
index 23c0d24..c5f1748 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses Mali DDK/kernel events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses Mali DDK/kernel trace events.
@@ -305,8 +305,8 @@
       var counter = this.model_.kernel.
           getOrCreateCounter('DVFS', counterName);
       if (counter.numSeries === 0) {
-        counter.addSeries(new tv.c.trace_model.CounterSeries(seriesName,
-            tv.b.ui.getColorIdForGeneralPurposeString(counter.name)));
+        counter.addSeries(new tr.model.CounterSeries(seriesName,
+            tr.b.ui.getColorIdForGeneralPurposeString(counter.name)));
       }
       counter.series.forEach(function(series) {
         series.addCounterSample(ts, value);
@@ -349,8 +349,8 @@
       var counter = this.model_.kernel.
           getOrCreateCounter(cat, counterName);
       if (counter.numSeries === 0) {
-        counter.addSeries(new tv.c.trace_model.CounterSeries(seriesName,
-            tv.b.ui.getColorIdForGeneralPurposeString(counter.name)));
+        counter.addSeries(new tr.model.CounterSeries(seriesName,
+            tr.b.ui.getColorIdForGeneralPurposeString(counter.name)));
       }
       counter.series.forEach(function(series) {
         series.addCounterSample(ts, value);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser_test.html
index 0c680bf..e2c86d2 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/mali_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('maliDDKImport', function() {
     var linesNoThread = [
       // Row 1 open
@@ -181,9 +181,9 @@
           'gles/src/dispatch/mali_gles_dispatch_entrypoints.c@992'
     ];
     var traceNoThread =
-        new tv.c.TraceModel(linesNoThread.join('\n'), false);
+        new tr.Model(linesNoThread.join('\n'), false);
     var traceWithThread =
-        new tv.c.TraceModel(linesWithThread.join('\n'), false);
+        new tr.Model(linesWithThread.join('\n'), false);
     assert.isFalse(traceNoThread.hasImportWarnings);
     assert.isFalse(traceWithThread.hasImportWarnings);
 
@@ -207,7 +207,7 @@
       '     kworker/u:0-5     [000] ....  1183.840486: mali_dvfs_set_clock: ' +
                      'frequency=400'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var counters = m.getAllCounters();
@@ -225,7 +225,7 @@
       '    kworker/u:0-5     [000] ....  1183.840009: mali_dvfs_set_voltage: ' +
                      'voltage=1100000'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var counters = m.getAllCounters();
@@ -243,7 +243,7 @@
       '     kworker/u:0-5     [000] ....  1183.840486: mali_dvfs_event: ' +
                      'utilization=37'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var counters = m.getAllCounters();
@@ -463,7 +463,7 @@
       '     kworker/u:0-5     [000] ....    79.046851: ' +
                      'mali_hwc_VCACHE_MISS: val=70'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var counters = m.getAllCounters();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser.html
index 45d89fb..26d289b 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser.html
@@ -13,8 +13,8 @@
 /**
  * @fileoverview Parses drm driver events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
-  var Parser = tv.e.importer.linux_perf.Parser;
+tr.exportTo('tr.e.importer.linux_perf', function() {
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux vmscan trace events.
@@ -55,9 +55,9 @@
     openAsyncSlice: function(ts, category, threadName, pid, key, name) {
       var kthread = this.importer.getOrCreateKernelThread(
           category + ':' + threadName, pid);
-      var slice = new tv.c.trace_model.AsyncSlice(
+      var slice = new tr.model.AsyncSlice(
           category, name,
-          tv.c.getColorIdForGeneralPurposeString(name),
+          tr.c.getColorIdForGeneralPurposeString(name),
           ts);
       slice.startThread = kthread.thread;
 
@@ -77,7 +77,7 @@
           slice.args = args;
           slice.endThread = kthread.thread;
           slice.subSlices = [
-            new tv.c.trace_model.Slice(category, slice.title,
+            new tr.model.Slice(category, slice.title,
                 slice.colorId, slice.start, slice.args, slice.duration)
           ];
           kthread.thread.asyncSliceGroup.push(slice);
@@ -116,8 +116,8 @@
           'kswapd: ' + eventBase.threadName,
           pid, pid);
       if (kthread.openSliceTS) {
-        var slice = new tv.c.trace_model.Slice('', eventBase.threadName,
-            tv.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),
+        var slice = new tr.model.Slice('', eventBase.threadName,
+            tr.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),
             kthread.openSliceTS,
             {
                 order: kthread.order
@@ -159,9 +159,9 @@
           'direct reclaim: ' + eventBase.threadName,
           pid, pid);
       if (kthread.openSliceTS !== undefined) {
-        var slice = new tv.c.trace_model.Slice(
+        var slice = new tr.model.Slice(
             '', 'direct reclaim',
-            tv.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),
+            tr.b.ui.getColorIdForGeneralPurposeString(eventBase.threadName),
             kthread.openSliceTS,
             {
                 order: kthread.order,
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser_test.html
index f465ab7..3f06027 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/memreclaim_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('memreclaimImport', function() {
     var lines = [
       ' surfaceflinger-1155  ( 1155) [001] ...1 12839.528756: ' +
@@ -24,7 +24,7 @@
       ' kswapd0-33    (   33) [001] ...1 12838.529770: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
       ' kswapd0-33    (   33) [001] ...1 12840.545737: mm_vmscan_kswapd_sleep: nid=0' // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     assert.equal(m.processes['1155'].threads['1155'].sliceGroup.length, 1);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/parser.html
index e2cb18f..451ec3f 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/parser.html
@@ -20,7 +20,7 @@
  * and their constructor must register their event handlers with the
  * importer.  For example,
  *
- * var Parser = tv.e.importer.linux_perf.Parser;
+ * var Parser = tr.e.importer.linux_perf.Parser;
  *
  * function WorkqueueParser(importer) {
  *   Parser.call(this, importer);
@@ -57,15 +57,15 @@
  *
  * All subclasses should depend on importer.linux_perf.parser, e.g.
  *
- * tv.defineModule('importer.linux_perf.workqueue_parser')
+ * tr.defineModule('importer.linux_perf.workqueue_parser')
  *   .dependsOn('importer.linux_perf.parser')
  *   .exportsTo('tracing', function()
  *
  * and be listed in the dependsOn of LinuxPerfImporter.  Beware that after
  * adding a new subclass you must run build/generate_about_tracing_contents.py
- * to regenerate tv.e.about_tracing.*.
+ * to regenerate tr.e.about_tracing.*.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
   /**
    * Parses linux perf events.
    * @constructor
@@ -79,9 +79,9 @@
     __proto__: Object.prototype
   };
 
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
   options.mandatoryBaseClass = Parser;
-  tv.b.decorateExtensionRegistry(Parser, options);
+  tr.b.decorateExtensionRegistry(Parser, options);
 
   return {
     Parser: Parser
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser.html
index 09b7889..23eccc6 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/extras/importer/linux_perf/parser.html">
-<link rel="import" href="/core/trace_model/counter_series.html">
+<link rel="import" href="/model/counter_series.html">
 
 <script>
 'use strict';
@@ -14,9 +14,9 @@
 /**
  * @fileoverview Parses power events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux power trace events.
@@ -53,8 +53,8 @@
       }
       powerCounter = targetCpu.getOrCreateCounter('', 'C-State');
       if (powerCounter.numSeries === 0) {
-        powerCounter.addSeries(new tv.c.trace_model.CounterSeries('state',
-            tv.b.ui.getColorIdForGeneralPurposeString(
+        powerCounter.addSeries(new tr.model.CounterSeries('state',
+            tr.b.ui.getColorIdForGeneralPurposeString(
                 powerCounter.name + '.' + 'state')));
       }
       powerCounter.series.forEach(function(series) {
@@ -66,8 +66,8 @@
       var targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
       var powerCounter = targetCpu.getOrCreateCounter('', 'C-State');
       if (powerCounter.numSeries === 0) {
-        powerCounter.addSeries(new tv.c.trace_model.CounterSeries('state',
-            tv.b.ui.getColorIdForGeneralPurposeString(powerCounter.name)));
+        powerCounter.addSeries(new tr.model.CounterSeries('state',
+            tr.b.ui.getColorIdForGeneralPurposeString(powerCounter.name)));
       }
       // NB: 4294967295/-1 means an exit from the current state
       var val = (cpuState != 4294967295 ? cpuState + 1 : 0);
@@ -81,8 +81,8 @@
       var powerCounter =
           targetCpu.getOrCreateCounter('', 'Clock Frequency');
       if (powerCounter.numSeries === 0) {
-        powerCounter.addSeries(new tv.c.trace_model.CounterSeries('state',
-            tv.b.ui.getColorIdForGeneralPurposeString(
+        powerCounter.addSeries(new tr.model.CounterSeries('state',
+            tr.b.ui.getColorIdForGeneralPurposeString(
                 powerCounter.name + '.' + 'state')));
       }
       powerCounter.series.forEach(function(series) {
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser_test.html
index 5ffbf56..f1a3559 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/power_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('powerFrequencyImport', function() {
     var lines = [
       ' kworker/0:3-6880  [000]  2784.783015: power_frequency: ' +
@@ -21,7 +21,7 @@
       ' kworker/1:2-7269  [001]  2784.993120: power_frequency: ' +
                  'type=2 state=1300000 cpu_id=1'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c0 = m.kernel.cpus[0];
@@ -44,7 +44,7 @@
       '     kworker/0:2-7972  [000] 15051.020304: cpu_frequency: ' +
                      'state=800000 cpu_id=0'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c0 = m.kernel.cpus[0];
@@ -71,7 +71,7 @@
       '          <idle>-0     [001] 15050.993457: cpu_idle: ' +
           'state=4294967295 cpu_id=1'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var c0 = m.kernel.cpus[0];
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser.html
index d41b7ef..e451498 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses regulator events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux regulator trace events.
@@ -54,16 +54,16 @@
   RegulatorParser.prototype = {
     __proto__: Parser.prototype,
 
-    /*
+    /**
      * Get or create a counter with one series.
      */
     getCtr_: function(ctrName, valueName) {
       var ctr = this.model_.kernel
         .getOrCreateCounter(null, 'vreg ' + ctrName + ' ' + valueName);
-      //Initialize the counter's series fields if needed.
+      // Initialize the counter's series fields if needed.
       if (ctr.series[0] === undefined) {
-        ctr.addSeries(new tv.c.trace_model.CounterSeries(valueName,
-        tv.b.ui.getColorIdForGeneralPurposeString(
+        ctr.addSeries(new tr.model.CounterSeries(valueName,
+        tr.b.ui.getColorIdForGeneralPurposeString(
         ctrName + '.' + valueName)));
       }
       return ctr;
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser_test.html
index 739026e..c49e1fe 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/regulator_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('regulatorImport', function() {
     var lines = [
       ' kworker/0:2H-14312 [000] ...1 143713.787749: ' +
@@ -33,7 +33,7 @@
       'kworker/0:1-30321 [000] ...1 144568.654785: ' +
         'regulator_disable_complete: name=8941_smbb_boost'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     console.log(m.importWarnings);
     assert.isFalse(m.hasImportWarnings);
 
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser.html
index c9fc913..228c3c1 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses scheduler events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux sched trace events.
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser_test.html
index dc11d8e..4f77404 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/sched_parser_test.html
@@ -11,9 +11,9 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('schedSwitchRE', function() {
-    var re = tv.e.importer.linux_perf._SchedParserTestExports.schedSwitchRE;
+    var re = tr.e.importer.linux_perf._SchedParserTestExports.schedSwitchRE;
     var x = re.exec('prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ' +
         '==> next_comm=SurfaceFlinger next_pid=178 next_prio=112');
     assert.isNotNull(x);
@@ -44,7 +44,7 @@
   });
 
   test('schedWakeupRE', function() {
-    var re = tv.e.importer.linux_perf._SchedParserTestExports.schedWakeupRE;
+    var re = tr.e.importer.linux_perf._SchedParserTestExports.schedWakeupRE;
     var x = re.exec(
         'comm=SensorService pid=207 prio=112 success=1 target_cpu=000');
     assert.isNotNull(x);
@@ -66,7 +66,7 @@
       '       Binder_1-217   [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=ndroid.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var thread = m.findAllThreadsNamed('Binder_1')[0];
@@ -108,7 +108,7 @@
 
     var m;
     assert.doesNotThrow(function() {
-      m = new tv.c.TraceModel(lines.join('\n'), false);
+      m = new tr.Model(lines.join('\n'), false);
     });
     assert.isTrue(m.hasImportWarnings);
     assert.equal(m.importWarnings[0].message, 'Unrecognized sleep state: F|O');
@@ -148,7 +148,7 @@
           '==> next_comm=ndroid.launcher next_pid=584 next_prio=120'
     ];
 
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var thread = m.findAllThreadsNamed('Binder_1')[0];
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser.html
index b46596d..f13013e 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses sync events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux sync trace events.
@@ -59,9 +59,9 @@
         var value = thread.lastActiveValue;
         if (value == undefined)
           value = ' ';
-        var slice = new tv.c.trace_model.Slice(
+        var slice = new tr.model.Slice(
             '', value,
-            tv.b.ui.getColorIdForGeneralPurposeString(value),
+            tr.b.ui.getColorIdForGeneralPurposeString(value),
             thread.lastActiveTs, {},
             duration);
         thread.thread.sliceGroup.pushSlice(slice);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser_test.html
index f69a037..9db5226 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/sync_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('syncEventImport', function() {
     var lines = [
       's3c-fb-92            (     0) [000] ...1  7206.550061: sync_timeline: name=s3c-fb value=7094', // @suppress longLineCheck
@@ -32,7 +32,7 @@
       's3c-fb-92            (     0) [000] ...1  7206.591244: sync_wait: end name=vb2 state=1' // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     var threads = m.getAllThreads();
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser.html
index 1437011..5e5c9b8 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser.html
@@ -13,9 +13,9 @@
 /**
  * @fileoverview Parses workqueue events in the Linux event trace format.
  */
-tv.exportTo('tv.e.importer.linux_perf', function() {
+tr.exportTo('tr.e.importer.linux_perf', function() {
 
-  var Parser = tv.e.importer.linux_perf.Parser;
+  var Parser = tr.e.importer.linux_perf.Parser;
 
   /**
    * Parses linux workqueue trace events.
@@ -68,8 +68,8 @@
       var kthread = this.importer.getOrCreateKernelThread(eventBase.threadName,
           pid, pid);
       if (kthread.openSlice) {
-        var slice = new tv.c.trace_model.Slice('', kthread.openSlice,
-            tv.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
+        var slice = new tr.model.Slice('', kthread.openSlice,
+            tr.b.ui.getColorIdForGeneralPurposeString(kthread.openSlice),
             kthread.openSliceTS,
             {},
             ts - kthread.openSliceTS);
diff --git a/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser_test.html b/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser_test.html
index 7fe4822..2cbb03f 100644
--- a/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/linux_perf/workqueue_parser_test.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('workQueueImport', function() {
     var lines = [
       ' kworker/0:3-6880  [000]  2784.771958: workqueue_execute_start: ' +
@@ -23,7 +23,7 @@
       ' kworker/1:2-7269  [001]  2784.805975: workqueue_execute_end: ' +
                  'work struct ffff88014fb0f158'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isFalse(m.hasImportWarnings);
 
     assert.equal(m.processes['6880'].threads['6880'].sliceGroup.length, 1);
diff --git a/trace-viewer/trace_viewer/extras/importer/trace2html_importer.html b/trace-viewer/trace_viewer/extras/importer/trace2html_importer.html
index 6b3830c..7202e1a 100644
--- a/trace-viewer/trace_viewer/extras/importer/trace2html_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/trace2html_importer.html
@@ -5,15 +5,15 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/importer/simple_line_reader.html">
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/importer/simple_line_reader.html">
 <link rel="import" href="/base/base64.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.importer', function() {
+tr.exportTo('tr.e.importer', function() {
 
   function Trace2HTMLImporter(model, events) {
     this.importPriority = 0;
@@ -25,12 +25,13 @@
     // Clear the array before pushing data to it.
     Trace2HTMLImporter.subtraces_ = [];
 
-    var r = new tv.c.importer.SimpleLineReader(text);
+    var r = new tr.importer.SimpleLineReader(text);
 
     // Try to find viewer-data...
     while (true) {
       if (!r.advanceToLineMatching(
-          /^<\s*script id="viewer-data" type="application\/json">$/))
+          new RegExp('^<\s*script id="viewer-data" ' +
+                     'type="(application\/json|text\/plain)">$')))
         break;
 
       r.beginSavingLines();
@@ -43,8 +44,8 @@
       raw_events = raw_events.slice(1, raw_events.length - 1);
       var data64 = raw_events.join('\n');
       var buffer = new ArrayBuffer(
-          tv.b.Base64.getDecodedBufferLength(data64));
-      var len = tv.b.Base64.DecodeToTypedArray(data64, new DataView(buffer));
+          tr.b.Base64.getDecodedBufferLength(data64));
+      var len = tr.b.Base64.DecodeToTypedArray(data64, new DataView(buffer));
       Trace2HTMLImporter.subtraces_.push(buffer.slice(0, len));
     }
   }
@@ -65,7 +66,7 @@
   };
 
   Trace2HTMLImporter.prototype = {
-    __proto__: tv.c.importer.Importer.prototype,
+    __proto__: tr.importer.Importer.prototype,
 
     isTraceDataContainer: function() {
       return true;
@@ -80,7 +81,7 @@
   };
 
 
-  tv.c.importer.Importer.register(Trace2HTMLImporter);
+  tr.importer.Importer.register(Trace2HTMLImporter);
 
 
   return {
diff --git a/trace-viewer/trace_viewer/extras/importer/trace2html_importer_test.html b/trace-viewer/trace_viewer/extras/importer/trace2html_importer_test.html
index 006d9e0..9e2b9d5 100644
--- a/trace-viewer/trace_viewer/extras/importer/trace2html_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/trace2html_importer_test.html
@@ -10,23 +10,23 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   test('simple', function() {
     var html_lines = [
       '<!DOCTYPE HTML>',
       '<script id="viewer-data" type="application/json">',
       btoa('hello'),
       '<\/script>',
-      '<script id="viewer-data" type="application/json">',
+      '<script id="viewer-data" type="text/plain">',
       btoa('world'),
       '<\/script>',
       '</html>'
     ];
     var html_text = html_lines.join('\n');
-    assert.isTrue(tv.e.importer.Trace2HTMLImporter.canImport(html_text));
+    assert.isTrue(tr.e.importer.Trace2HTMLImporter.canImport(html_text));
 
-    var m = new tv.c.TraceModel();
-    var imp = new tv.e.importer.Trace2HTMLImporter(m, html_text);
+    var m = new tr.Model();
+    var imp = new tr.e.importer.Trace2HTMLImporter(m, html_text);
     var subTracesAsBuffers = imp.extractSubtraces();
     var subTracesAsStrings = subTracesAsBuffers.map(function(buffer) {
       var str = '';
diff --git a/trace-viewer/trace_viewer/extras/importer/trace_event_importer.html b/trace-viewer/trace_viewer/extras/importer/trace_event_importer.html
index 88490a6..a374dbe 100644
--- a/trace-viewer/trace_viewer/extras/importer/trace_event_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/trace_event_importer.html
@@ -8,19 +8,19 @@
 <link rel="import" href="/base/ui/color_scheme.html">
 <link rel="import" href="/base/quad.html">
 <link rel="import" href="/base/range.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/trace_model/attribute.html">
-<link rel="import" href="/core/trace_model/comment_box_annotation.html">
-<link rel="import" href="/core/trace_model/instant_event.html">
-<link rel="import" href="/core/trace_model/flow_event.html">
-<link rel="import" href="/core/trace_model/counter_series.html">
-<link rel="import" href="/core/trace_model/slice_group.html">
-<link rel="import" href="/core/trace_model/global_memory_dump.html">
-<link rel="import" href="/core/trace_model/memory_allocator_dump.html">
-<link rel="import" href="/core/trace_model/process_memory_dump.html">
-<link rel="import" href="/core/trace_model/rect_annotation.html">
-<link rel="import" href="/core/trace_model/x_marker_annotation.html">
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/comment_box_annotation.html">
+<link rel="import" href="/model/instant_event.html">
+<link rel="import" href="/model/flow_event.html">
+<link rel="import" href="/model/counter_series.html">
+<link rel="import" href="/model/slice_group.html">
+<link rel="import" href="/model/global_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
+<link rel="import" href="/model/process_memory_dump.html">
+<link rel="import" href="/model/rect_annotation.html">
+<link rel="import" href="/model/x_marker_annotation.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
@@ -29,9 +29,9 @@
  * @fileoverview TraceEventImporter imports TraceEvent-formatted data
  * into the provided model.
  */
-tv.exportTo('tv.e.importer', function() {
+tr.exportTo('tr.e.importer', function() {
 
-  var Importer = tv.c.importer.Importer;
+  var Importer = tr.importer.Importer;
 
   function deepCopy(value) {
     if (!(value instanceof Object)) {
@@ -200,7 +200,7 @@
       var thread = this.model_.getOrCreateProcess(event.pid).
           getOrCreateThread(event.tid);
       this.allFlowEvents_.push({
-        refGuid: tv.b.GUID.getLastGuid(),
+        refGuid: tr.b.GUID.getLastGuid(),
         sequenceNumber: this.allFlowEvents_.length,
         event: event,
         thread: thread
@@ -224,9 +224,9 @@
       // Initialize the counter's series fields if needed.
       if (ctr.numSeries === 0) {
         for (var seriesName in event.args) {
-          ctr.addSeries(new tv.c.trace_model.CounterSeries(
+          ctr.addSeries(new tr.model.CounterSeries(
               seriesName,
-              tv.b.ui.getColorIdForGeneralPurposeString(
+              tr.b.ui.getColorIdForGeneralPurposeString(
                   ctr.name + '.' + seriesName)));
         }
 
@@ -385,10 +385,10 @@
       var constructor;
       switch (event.s) {
         case 'g':
-          constructor = tv.c.trace_model.GlobalInstantEvent;
+          constructor = tr.model.GlobalInstantEvent;
           break;
         case 'p':
-          constructor = tv.c.trace_model.ProcessInstantEvent;
+          constructor = tr.model.ProcessInstantEvent;
           break;
         default:
           this.model_.importWarning({
@@ -398,16 +398,16 @@
           return;
       }
 
-      var colorId = tv.b.ui.getColorIdForGeneralPurposeString(event.name);
+      var colorId = tr.b.ui.getColorIdForGeneralPurposeString(event.name);
       var instantEvent = new constructor(event.cat, event.name,
           colorId, event.ts / 1000, this.deepCopyIfNeeded_(event.args));
 
       switch (instantEvent.type) {
-        case tv.c.trace_model.InstantEventType.GLOBAL:
+        case tr.model.InstantEventType.GLOBAL:
           this.model_.pushInstantEvent(instantEvent);
           break;
 
-        case tv.c.trace_model.InstantEventType.PROCESS:
+        case tr.model.InstantEventType.PROCESS:
           var process = this.model_.getOrCreateProcess(event.pid);
           process.pushInstantEvent(instantEvent);
           break;
@@ -427,16 +427,16 @@
             event.name];
       }
       if (stackFrame === undefined) {
-        var id = 'te-' + tv.b.GUID.allocate();
-        stackFrame = new tv.c.trace_model.StackFrame(
+        var id = 'te-' + tr.b.GUID.allocate();
+        stackFrame = new tr.model.StackFrame(
             undefined, id,
             event.cat, event.name,
-            tv.b.ui.getColorIdForGeneralPurposeString(event.name));
+            tr.b.ui.getColorIdForGeneralPurposeString(event.name));
         this.model_.addStackFrame(stackFrame);
         this.traceEventSampleStackFramesByName_[event.name] = stackFrame;
       }
 
-      var sample = new tv.c.trace_model.Sample(
+      var sample = new tr.model.Sample(
           undefined, thread, 'TRACE_EVENT_SAMPLE',
           event.ts / 1000, stackFrame, 1,
           this.deepCopyIfNeeded_(event.args));
@@ -486,7 +486,7 @@
      * model_.
      */
     importEvents: function() {
-      var csr = new tv.c.ClockSyncRecord('ftrace_importer', 0, {});
+      var csr = new tr.ClockSyncRecord('ftrace_importer', 0, {});
       this.model_.clockSyncRecords.push(csr);
       if (this.stackFrameEvents_)
         this.importStackFrames_();
@@ -548,10 +548,10 @@
       for (var id in events) {
         var event = events[id];
         var textForColor = event.category ? event.category : event.name;
-        var frame = new tv.c.trace_model.StackFrame(
+        var frame = new tr.model.StackFrame(
             undefined, 'g' + id,
             event.category, event.name,
-            tv.b.ui.getColorIdForGeneralPurposeString(textForColor));
+            tr.b.ui.getColorIdForGeneralPurposeString(textForColor));
         m.addStackFrame(frame);
       }
       for (var id in events) {
@@ -576,7 +576,7 @@
 
     importAnnotations_: function() {
       for (var id in this.traceAnnotations_) {
-        var annotation = tv.c.trace_model.Annotation.fromDictIfPossible(
+        var annotation = tr.model.Annotation.fromDictIfPossible(
            this.traceAnnotations_[id]);
         if (!annotation) {
           this.model_.importWarning({
@@ -687,7 +687,7 @@
 
         var stackFrame = this.getStackFrameForEvent_(event);
 
-        var sample = new tv.c.trace_model.Sample(
+        var sample = new tr.model.Sample(
             cpu, thread,
             event.name, event.ts / 1000,
             stackFrame,
@@ -830,12 +830,12 @@
               // Include args for both END and BEGIN for a matched pair.
               var concatenateArguments = function(args1, args2) {
                 if (args1.params === undefined || args2.params === undefined)
-                  return tv.b.concatenateObjects(args1, args2);
+                  return tr.b.concatenateObjects(args1, args2);
                 // Make an argument object to hold the combined params.
                 var args3 = {};
-                args3.params = tv.b.concatenateObjects(args1.params,
+                args3.params = tr.b.concatenateObjects(args1.params,
                                                        args2.params);
-                return tv.b.concatenateObjects(args1, args2, args3);
+                return tr.b.concatenateObjects(args1, args2, args3);
               }
               var endArgs = eventStateEntry.end.event.args || {};
               sliceArgs = concatenateArguments(sliceArgs, endArgs);
@@ -859,7 +859,7 @@
 
           var isTopLevel = (eventStateEntry.parentEntry === undefined);
           var asyncSliceConstructor =
-             tv.c.trace_model.AsyncSlice.getConstructor(
+             tr.model.AsyncSlice.getConstructor(
                 eventStateEntry.event.cat,
                 eventStateEntry.event.name);
 
@@ -876,7 +876,7 @@
           var slice = new asyncSliceConstructor(
               eventStateEntry.event.cat,
               eventStateEntry.event.name,
-              tv.b.ui.getColorIdForGeneralPurposeString(
+              tr.b.ui.getColorIdForGeneralPurposeString(
                   eventStateEntry.event.name),
               startState.event.ts / 1000,
               sliceArgs,
@@ -980,15 +980,15 @@
           if (event.ph === 'F') {
             // Create a slice from start to end.
             var asyncSliceConstructor =
-               tv.c.trace_model.AsyncSlice.getConstructor(
+               tr.model.AsyncSlice.getConstructor(
                   events[0].event.cat,
                   name);
             var slice = new asyncSliceConstructor(
                 events[0].event.cat,
                 name,
-                tv.b.ui.getColorIdForGeneralPurposeString(name),
+                tr.b.ui.getColorIdForGeneralPurposeString(name),
                 events[0].event.ts / 1000,
-                tv.b.concatenateObjects(events[0].event.args,
+                tr.b.concatenateObjects(events[0].event.args,
                                       events[events.length - 1].event.args),
                 (event.ts - events[0].event.ts) / 1000,
                 true);
@@ -1036,13 +1036,13 @@
                 subName = subName + ':' + events[j].event.args.step;
 
               var asyncSliceConstructor =
-                 tv.c.trace_model.AsyncSlice.getConstructor(
+                 tr.model.AsyncSlice.getConstructor(
                     events[0].event.cat,
                     subName);
               var subSlice = new asyncSliceConstructor(
                   events[0].event.cat,
                   subName,
-                  tv.b.ui.getColorIdForGeneralPurposeString(subName + j),
+                  tr.b.ui.getColorIdForGeneralPurposeString(subName + j),
                   events[startIndex].event.ts / 1000,
                   this.deepCopyIfNeeded_(events[j].event.args),
                   (events[endIndex].event.ts - events[startIndex].event.ts) /
@@ -1108,11 +1108,11 @@
         if (startSlice === undefined)
           return undefined;
 
-        var flowEvent = new tv.c.trace_model.FlowEvent(
+        var flowEvent = new tr.model.FlowEvent(
             event.cat,
             event.id,
             event.name,
-            tv.b.ui.getColorIdForGeneralPurposeString(event.name),
+            tr.b.ui.getColorIdForGeneralPurposeString(event.name),
             event.ts / 1000,
             that.deepCopyIfNeeded_(event.args));
         flowEvent.startSlice = startSlice;
@@ -1120,10 +1120,11 @@
         return flowEvent;
       }
 
-      function finishFlowEventWith(flowEvent, thread, event, refGuid, isStep) {
+      function finishFlowEventWith(flowEvent, thread, event,
+                                   refGuid, bindToParent) {
         // TODO(nduca): Figure out endSlice from ts and binding point.
         var endSlice;
-        if (isStep) {
+        if (bindToParent) {
           endSlice = thread.sliceGroup.findSliceAtTs(event.ts / 1000);
         } else {
           endSlice = thread.sliceGroup.findNextSliceAfter(
@@ -1187,9 +1188,33 @@
             continue;
           }
 
-          var isStep = event.ph == 't';
+          var bindToParent = event.ph === 't';
+
+          if (event.ph === 'f') {
+            if (event.bp === undefined) {
+              // Hack: input latency flow events used to be issued without
+              // bp='e' letter in old traces. But, we still want their flow
+              // events to parse "properly." This adjusts their binding point
+              // so that they parse.
+              //
+              // TODO(nduca): Removal of this hack is tracked in
+              // https://github.com/google/trace-viewer/issues/991.
+              if (event.cat.indexOf('input') > -1)
+                bindToParent = true;
+            } else {
+              if (event.bp !== 'e') {
+                this.model_.importWarning({
+                 type: 'flow_slice_bind_point_error',
+                 message: 'Flow event with invalid binding point (event.bp).'
+                });
+                continue;
+              }
+              bindToParent = true;
+            }
+          }
+
           var ok = finishFlowEventWith(flowEvent, thread, event,
-                                       refGuid, isStep);
+                                       refGuid, bindToParent);
           if (ok) {
             that.model_.flowEvents.push(flowEvent);
           } else {
@@ -1306,7 +1331,7 @@
         }
 
         if (instance) {
-          instance.colorId = tv.b.ui.getColorIdForGeneralPurposeString(
+          instance.colorId = tr.b.ui.getColorIdForGeneralPurposeString(
               instance.typeName);
         }
       }
@@ -1333,7 +1358,7 @@
     },
 
     createImplicitObjects_: function() {
-      tv.b.iterItems(this.model_.processes, function(pid, process) {
+      tr.b.iterItems(this.model_.processes, function(pid, process) {
         this.createImplicitObjectsForProcess_(process);
       }, this);
     },
@@ -1351,7 +1376,7 @@
           return;
 
         if (referencingObjectFieldValue instanceof
-            tv.c.trace_model.ObjectSnapshot)
+            tr.model.ObjectSnapshot)
           return null;
         if (referencingObjectFieldValue.id === undefined)
           return;
@@ -1396,7 +1421,7 @@
         res.containingSnapshot = containingSnapshot;
         res.snapshottedOnThread = containingSnapshot.snapshottedOnThread;
         referencingObject[referencingObjectFieldName] = res;
-        if (!(res instanceof tv.c.trace_model.ObjectSnapshot))
+        if (!(res instanceof tr.model.ObjectSnapshot))
           throw new Error('Created object must be instanceof snapshot');
         return res.args;
       }
@@ -1452,16 +1477,16 @@
     },
 
     createMemoryDumps_: function() {
-      tv.b.iterItems(this.allMemoryDumpEvents_, function(id, events) {
+      tr.b.iterItems(this.allMemoryDumpEvents_, function(id, events) {
         // Calculate the range of the global memory dump.
-        var range = new tv.b.Range();
+        var range = new tr.b.Range();
         if (events.global !== undefined)
           range.addValue(events.global.ts / 1000);
         for (var i = 0; i < events.process.length; i++)
           range.addValue(events.process[i].ts / 1000);
 
         // Create the global memory dump.
-        var globalMemoryDump = new tv.c.trace_model.GlobalMemoryDump(
+        var globalMemoryDump = new tr.model.GlobalMemoryDump(
             this.model_, range.min);
         globalMemoryDump.duration = range.range;
         this.model_.globalMemoryDumps.push(globalMemoryDump);
@@ -1500,7 +1525,7 @@
           }
 
           var process = this.model_.getOrCreateProcess(pid);
-          var processMemoryDump = new tv.c.trace_model.ProcessMemoryDump(
+          var processMemoryDump = new tr.model.ProcessMemoryDump(
               globalMemoryDump, process, processEvent.ts / 1000);
 
           // Parse the totals, which are mandatory.
@@ -1520,15 +1545,24 @@
 
           // Populate the vmRegions, if present.
           if (dumps.process_mmaps && dumps.process_mmaps.vm_regions) {
+            function parseByteStat(rawValue) {
+              if (rawValue === undefined)
+                return undefined;
+              return parseInt(rawValue, 16);
+            }
+
             processMemoryDump.vmRegions = dumps.process_mmaps.vm_regions.map(
               function(rawRegion) {
                 // See //base/trace_event/process_memory_maps.cc in Chromium.
-                var byteStats = new tv.c.trace_model.VMRegionByteStats(
-                    parseInt(rawRegion.bs.prv, 16),  // privateResident
-                    parseInt(rawRegion.bs.shr, 16),  // sharedResident
-                    parseInt(rawRegion.bs.pss, 16)  // proportionalResident
+                var byteStats = new tr.model.VMRegionByteStats(
+                  parseByteStat(rawRegion.bs.pc),
+                  parseByteStat(rawRegion.bs.pd),
+                  parseByteStat(rawRegion.bs.sc),
+                  parseByteStat(rawRegion.bs.sd),
+                  parseByteStat(rawRegion.bs.pss),
+                  parseByteStat(rawRegion.bs.sw)
                 );
-                return new tv.c.trace_model.VMRegion(
+                return new tr.model.VMRegion(
                     parseInt(rawRegion.sa, 16),  // startAddress
                     parseInt(rawRegion.sz, 16),  // sizeInBytes
                     rawRegion.pf,  // protectionFlags
@@ -1545,7 +1579,7 @@
             // Construct the MemoryAllocatorDump objects without parent links
             // and add them to the processMemoryAllocatorDumpsByName and
             // globalMemoryAllocatorDumpsByName indices appropriately.
-            tv.b.iterItems(dumps.allocators,
+            tr.b.iterItems(dumps.allocators,
                 function(fullName, rawAllocatorDump) {
               // Every memory allocator dump should have a GUID. If not, then
               // it cannot be associated with any edges.
@@ -1588,7 +1622,7 @@
                   });
                   return;
                 }
-                allocatorDump = new tv.c.trace_model.MemoryAllocatorDump(
+                allocatorDump = new tr.model.MemoryAllocatorDump(
                     containerMemoryDump, fullName, guid);
                 dstIndex[fullName] = allocatorDump;
                 if (guid !== undefined)
@@ -1619,7 +1653,7 @@
 
               // Add all new attributes to the memory allocator dump.
               var attributes = rawAllocatorDump.attrs;
-              tv.b.iterItems(attributes, function(attrName, attrArgs) {
+              tr.b.iterItems(attributes, function(attrName, attrArgs) {
                 if (attrName in allocatorDump.attributes) {
                   // Skip existing attributes of the memory allocator dump.
                   this.model_.importWarning({
@@ -1631,7 +1665,7 @@
                   return;
                 }
                 var attrValue =
-                    tv.c.trace_model.Attribute.fromDictIfPossible(attrArgs);
+                    tr.model.Attribute.fromDictIfPossible(attrArgs);
                 allocatorDump.addAttribute(attrName, attrValue);
               }, this);
             }, this);
@@ -1687,7 +1721,7 @@
             }
 
             var importance = rawEdge.importance;
-            var edge = new tv.c.trace_model.MemoryAllocatorDumpLink(
+            var edge = new tr.model.MemoryAllocatorDumpLink(
                 sourceDump, targetDump, importance);
 
             switch (rawEdge.type) {
@@ -1753,7 +1787,7 @@
           var parentAlreadyExisted = true;
           if (parentAllocatorDump === undefined) {
             parentAlreadyExisted = false;
-            parentAllocatorDump = new tv.c.trace_model.MemoryAllocatorDump(
+            parentAllocatorDump = new tr.model.MemoryAllocatorDump(
                 allocatorDump.containerMemoryDump, parentFullName);
             memoryAllocatorDumpsByFullName[parentFullName] =
                 parentAllocatorDump;
@@ -1773,15 +1807,11 @@
         }
       }, this);
 
-      rootAllocatorDumps.forEach(function(dump) {
-        dump.aggregateAttributes(this.model_);
-      }, this);
-
       return rootAllocatorDumps;
     },
 
     joinObjectRefs_: function() {
-      tv.b.iterItems(this.model_.processes, function(pid, process) {
+      tr.b.iterItems(this.model_.processes, function(pid, process) {
         this.joinObjectRefsForProcess_(process);
       }, this);
     },
@@ -1789,7 +1819,7 @@
     joinObjectRefsForProcess_: function(process) {
       // Iterate the world, looking for id_refs
       var patchupsToApply = [];
-      tv.b.iterItems(process.threads, function(tid, thread) {
+      tr.b.iterItems(process.threads, function(tid, thread) {
         thread.asyncSliceGroup.slices.forEach(function(item) {
           this.searchItemForIDRefs_(
               patchupsToApply, process.objects, 'start', item);
@@ -1838,9 +1868,9 @@
         if (!(object instanceof Object))
           return;
 
-        if ((object instanceof tv.c.trace_model.ObjectSnapshot) ||
+        if ((object instanceof tr.model.ObjectSnapshot) ||
             (object instanceof Float32Array) ||
-            (object instanceof tv.b.Quad))
+            (object instanceof tr.b.Quad))
           return;
 
         if (object instanceof Array) {
@@ -1862,7 +1892,7 @@
     }
   };
 
-  tv.c.importer.Importer.register(TraceEventImporter);
+  tr.importer.Importer.register(TraceEventImporter);
 
   return {
     TraceEventImporter: TraceEventImporter
diff --git a/trace-viewer/trace_viewer/extras/importer/trace_event_importer_perf_test.html b/trace-viewer/trace_viewer/extras/importer/trace_event_importer_perf_test.html
index ed609d8..eac9fd7 100644
--- a/trace-viewer/trace_viewer/extras/importer/trace_event_importer_perf_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/trace_event_importer_perf_test.html
@@ -6,13 +6,13 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/full_config.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   var eventStrings = {};
 
   // @const
@@ -59,14 +59,14 @@
   n110100.forEach(function(val) {
     timedPerfTestWithEvents(TEST_NAMES[0] + '_' + val, function() {
       var events = getEvents(TEST_FILES_PATHS[0]);
-      var m = new tv.c.TraceModel();
+      var m = new tr.Model();
       m.importTraces([events], false, false);
     }, {iterations: val});
   });
 
   timedPerfTestWithEvents(TEST_NAMES[1] + '_1', function() {
     var events = getEvents(TEST_FILES_PATHS[1]);
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false, false);
   }, {iterations: 1});
 });
diff --git a/trace-viewer/trace_viewer/extras/importer/trace_event_importer_test.html b/trace-viewer/trace_viewer/extras/importer/trace_event_importer_test.html
index bd05b79..8e5fda9 100644
--- a/trace-viewer/trace_viewer/extras/importer/trace_event_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/trace_event_importer_test.html
@@ -11,12 +11,12 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
-  var findSliceNamed = tv.c.test_utils.findSliceNamed;
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
+  var findSliceNamed = tr.c.test_utils.findSliceNamed;
 
   test('canImportEmpty', function() {
-    assert.isFalse(tv.e.importer.TraceEventImporter.canImport([]));
-    assert.isFalse(tv.e.importer.TraceEventImporter.canImport(''));
+    assert.isFalse(tr.e.importer.TraceEventImporter.canImport([]));
+    assert.isFalse(tr.e.importer.TraceEventImporter.canImport(''));
   });
 
   test('basicSingleThreadNonnestedParsing', function() {
@@ -27,7 +27,7 @@
       {name: 'b', args: {}, pid: 52, ts: 631, cat: 'bar', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[52];
     assert.isDefined(p);
@@ -60,7 +60,7 @@
       {name: 'b', args: {}, pid: 52, ts: 631, cat: 'bar', tid: 53, ph: 'E', tts: 331}  // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[52];
     assert.isDefined(p);
@@ -105,7 +105,7 @@
         ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[1].threads[1];
     var sA = findSliceNamed(t.sliceGroup, 'a');
 
@@ -122,7 +122,7 @@
     ];
 
     // This should not throw an exception.
-    new tv.c.TraceModel(events);
+    new tr.Model(events);
   });
 
   test('importDoesNotChokeOnNulls', function() {
@@ -132,7 +132,7 @@
     ];
 
     // This should not throw an exception.
-    new tv.c.TraceModel(events);
+    new tr.Model(events);
   });
 
   test('categoryBeginEndMismatchPrefersBegin', function() {
@@ -141,7 +141,7 @@
       {name: 'a', args: {}, pid: 52, ts: 560, cat: 'bar', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[52];
     assert.isDefined(p);
@@ -162,7 +162,7 @@
       {name: 'b', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.isTrue(m.hasImportWarnings);
     assert.equal(m.importWarnings.length, 1);
   });
@@ -174,7 +174,7 @@
       {name: 'b', args: {}, pid: 1, ts: 3, tts: 3, cat: 'bar', tid: 1, ph: 'E'},
       {name: 'a', args: {}, pid: 1, ts: 4, tts: 3, cat: 'foo', tid: 1, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var t = m.processes[1].threads[1];
 
     var sA = findSliceNamed(t.sliceGroup, 'a');
@@ -206,7 +206,7 @@
       {name: 'c', args: {}, pid: 1, ts: 7, tts: 6, cat: 'baz', tid: 1, ph: 'E'},
       {name: 'a', args: {}, pid: 1, ts: 8, tts: 8, cat: 'foo', tid: 1, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var t = m.processes[1].threads[1];
 
     var sA = findSliceNamed(t.sliceGroup, 'a');
@@ -246,7 +246,7 @@
       {name: 'b', args: {}, pid: 1, ts: 7, cat: 'bar', tid: 1, ph: 'E'},
       {name: 'a', args: {}, pid: 1, ts: 8, cat: 'foo', tid: 1, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var t = m.processes[1].threads[1];
 
     var sA = findSliceNamed(t.sliceGroup, 'a');
@@ -289,7 +289,7 @@
       {name: 'b', args: {}, pid: 1, ts: 1, cat: 'bar', tid: 2, ph: 'B'},
       {name: 'b', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 2, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[1];
     var t = p.threads[1];
     var slice = t.sliceGroup.slices[0];
@@ -305,7 +305,7 @@
       // Slice that doesn't finish.
       {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[1];
     var t = p.threads[1];
     var slice = t.sliceGroup.slices[0];
@@ -323,7 +323,7 @@
       {name: 'b1', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'E'},
       {name: 'b2', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var t = m.processes[1].threads[1];
 
     var sA = findSliceNamed(t.sliceGroup, 'a');
@@ -345,7 +345,7 @@
       {name: 'c', args: {}, pid: 1, ts: 1, cat: 'bar', tid: 2, ph: 'B'},
       {name: 'c', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 2, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.processes[1];
     var t = p.threads[1];
     assert.equal(t.sliceGroup.length, 2);
@@ -377,7 +377,7 @@
       {name: 'b', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 2, ph: 'B'},
       {name: 'b', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 2, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var t1 = m.processes[1].threads[1];
     var t2 = m.processes[1].threads[2];
 
@@ -392,7 +392,7 @@
   test('taskColoring', function() {
     // The test below depends on hashing of 'a' != 'b'. Fail early if that
     // assumption is incorrect.
-    assert.notEqual(tv.b.ui.getStringHash('a'), tv.b.ui.getStringHash('b'));
+    assert.notEqual(tr.b.ui.getStringHash('a'), tr.b.ui.getStringHash('b'));
 
     var events = [
       {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
@@ -402,7 +402,7 @@
       {name: 'a', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 1, ph: 'B'},
       {name: 'a', args: {}, pid: 1, ts: 6, cat: 'baz', tid: 1, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[1];
     var t = p.threads[1];
     var a1 = t.sliceGroup.slices[0];
@@ -425,7 +425,7 @@
       {name: 'b', args: {}, pid: 1, ts: 3, cat: 'bar', tid: 2, ph: 'B'},
       {name: 'b', args: {}, pid: 1, ts: 4, cat: 'bar', tid: 2, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[1];
     assert.isDefined(p);
@@ -466,7 +466,7 @@
       {name: 'b', args: {}, pid: 2, ts: 3, cat: 'bar', tid: 2, ph: 'B'},
       {name: 'b', args: {}, pid: 2, ts: 4, cat: 'bar', tid: 2, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 2);
     var p = m.processes[1];
     assert.isDefined(p);
@@ -515,7 +515,7 @@
       {name: 'process_name', args: {name: 'SomeProcessName'},
         pid: 2, ts: 0, tid: 1, ph: 'M'}
     ];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false, false);
     assert.equal(m.processes[1].name, 'SomeProcessName');
   });
@@ -528,7 +528,7 @@
       {name: 'process_labels', args: {labels: 'baz'},
         pid: 2, ts: 0, tid: 1, ph: 'M'}
     ];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false, false);
     assert.deepEqual(m.processes[1].labels, ['foo', 'bar', 'baz']);
     assert.deepEqual(m.processes[2].labels, ['baz']);
@@ -544,7 +544,7 @@
       {name: 'process_sort_index', args: {sort_index: 1},
         pid: 1, ts: 0, tid: 1, ph: 'M'}
     ];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false, false);
 
     // By name, p1 is before p2. But, its sort index overrides that.
@@ -559,7 +559,7 @@
       {name: 'thread_name', args: {name: 'Thread 2'},
         pid: 2, ts: 0, tid: 2, ph: 'M'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     m.importTraces([events], false, false);
     assert.equal(m.processes[1].threads[1].name, 'Thread 1');
     assert.equal(m.processes[2].threads[2].name, 'Thread 2');
@@ -575,7 +575,7 @@
       {name: 'thread_sort_index', args: {sort_index: 1},
         pid: 1, ts: 0, tid: 1, ph: 'M'}
     ];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false, false);
 
     // By name, t1 is before t2. But, its sort index overrides that.
@@ -592,7 +592,7 @@
       {name: 'num_cpus', args: {number: 4},
         pid: 14, ts: 0, tid: 0, ph: 'M'}
     ];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false, false);
     assert.equal(m.kernel.softwareMeasuredCpuCount, 4);
     assert.equal(m.kernel.bestGuessAtCpuCount, 4);
@@ -605,7 +605,7 @@
       {name: 'num_cpus', args: {number: 1},
         pid: 14, ts: 0, tid: 0, ph: 'M'}
     ];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false, false);
     assert.equal(m.kernel.softwareMeasuredCpuCount, 4);
     assert.equal(m.kernel.bestGuessAtCpuCount, 4);
@@ -617,7 +617,7 @@
       {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'B'},
       {name: 'a', args: {}, pid: 1, ts: 5, cat: 'foo', tid: 1, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.processes[1];
     var t = p.threads[1];
     assert.equal(t.sliceGroup.length, 1);
@@ -638,7 +638,7 @@
       {name: 'slower', args: {}, pid: 1, ts: 4, cat: 'baz', tid: 1, ph: 'i'},
       {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'E'}
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.processes[1];
     var t = p.threads[1];
 
@@ -677,7 +677,7 @@
         ph: 'C'}
 
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[1];
     var ctr = m.processes[1].counters['foo.ctr'];
 
@@ -688,7 +688,7 @@
 
     assert.equal(ctr.series[0].name, 'value');
     assert.equal(ctr.series[0].color,
-                 tv.b.ui.getColorIdForGeneralPurposeString('ctr.value'));
+                 tr.b.ui.getColorIdForGeneralPurposeString('ctr.value'));
 
     assert.deepEqual(ctr.timestamps, [0, 0.01, 0.02]);
 
@@ -717,7 +717,7 @@
       {name: 'ctr', args: {'value': 40}, pid: 1, ts: 20, cat: 'bar', tid: 1,
         ph: 'C', id: 2}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[1];
     var ctr = m.processes[1].counters['foo.ctr[0]'];
     assert.equal(ctr.name, 'ctr[0]');
@@ -759,11 +759,11 @@
   });
 
   test('multiCounterUpdateBounds', function() {
-    var ctr = new tv.c.trace_model.Counter(undefined, 'testBasicCounter',
+    var ctr = new tr.model.Counter(undefined, 'testBasicCounter',
         '', 'testBasicCounter');
-    var value1Series = new tv.c.trace_model.CounterSeries(
+    var value1Series = new tr.model.CounterSeries(
         'value1', 'testBasicCounter.value1');
-    var value2Series = new tv.c.trace_model.CounterSeries(
+    var value2Series = new tr.model.CounterSeries(
         'value2', 'testBasicCounter.value2');
     ctr.addSeries(value1Series);
     ctr.addSeries(value2Series);
@@ -807,7 +807,7 @@
       {name: 'ctr', args: {'value1': 10, 'value2': 4}, pid: 1, ts: 10, cat: 'foo', tid: 1, ph: 'C'}, // @suppress longLineCheck
       {name: 'ctr', args: {'value1': 0, 'value2': 1 }, pid: 1, ts: 20, cat: 'foo', tid: 1, ph: 'C'} // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[1];
     var ctr = m.processes[1].counters['foo.ctr'];
     assert.equal(ctr.name, 'ctr');
@@ -820,9 +820,9 @@
     assert.equal(ctr.series[0].name, 'value1');
     assert.equal(ctr.series[1].name, 'value2');
     assert.equal(ctr.series[0].color,
-                 tv.b.ui.getColorIdForGeneralPurposeString('ctr.value1'));
+                 tr.b.ui.getColorIdForGeneralPurposeString('ctr.value1'));
     assert.equal(ctr.series[1].color,
-                 tv.b.ui.getColorIdForGeneralPurposeString('ctr.value2'));
+                 tr.b.ui.getColorIdForGeneralPurposeString('ctr.value2'));
 
     assert.deepEqual(ctr.timestamps, [0, 0.01, 0.02]);
     var samples = [];
@@ -848,7 +848,7 @@
       {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
     ] };
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
   });
 
@@ -858,7 +858,7 @@
       {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(JSON.stringify(events));
+    var m = new tr.Model(JSON.stringify(events));
     assert.equal(m.numProcesses, 1);
   });
 
@@ -868,7 +868,7 @@
       {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(' ' + JSON.stringify(events));
+    var m = new tr.Model(' ' + JSON.stringify(events));
     assert.equal(m.numProcesses, 1);
   });
 
@@ -878,7 +878,7 @@
       {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(JSON.stringify(events) + '\n');
+    var m = new tr.Model(JSON.stringify(events) + '\n');
     assert.equal(m.numProcesses, 1);
   });
 
@@ -893,7 +893,7 @@
 
     // Drop off the trailing ]
     var dropped = tmp.substring(0, tmp.length - 1);
-    var m = new tv.c.TraceModel(dropped);
+    var m = new tr.Model(dropped);
     assert.equal(m.numProcesses, 1);
   });
 
@@ -905,7 +905,7 @@
     ];
     var text = lines.join('\n');
 
-    var m = new tv.c.TraceModel(text);
+    var m = new tr.Model(text);
     assert.equal(m.numProcesses, 1);
     assert.equal(m.processes[52].threads[53].sliceGroup.length, 1);
   });
@@ -921,7 +921,7 @@
 
     // Drop off the trailing ] and add a newline
     var dropped = tmp.substring(0, tmp.length - 1);
-    var m = new tv.c.TraceModel(dropped + '\n');
+    var m = new tr.Model(dropped + '\n');
     assert.equal(m.numProcesses, 1);
   });
 
@@ -933,7 +933,7 @@
     ];
     var text = lines.join('\r\n');
 
-    var m = new tv.c.TraceModel(text);
+    var m = new tr.Model(text);
     assert.equal(m.numProcesses, 1);
     assert.equal(m.processes[52].threads[53].sliceGroup.length, 1);
   });
@@ -946,7 +946,7 @@
       ']'
     ];
     var text = lines.join('\n');
-    var m = new tv.c.TraceModel(text);
+    var m = new tr.Model(text);
     assert.equal(m.numProcesses, 1);
     assert.equal(m.processes[9].threads[8].sliceGroup.length, 1);
   });
@@ -960,7 +960,7 @@
         ph: 'S', id: 72, args: {'foo': 'bar'}}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -982,7 +982,7 @@
       {name: 'a', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[52];
     assert.isDefined(p);
@@ -1007,7 +1007,7 @@
       {name: 'b', args: {z: 4}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[52];
     assert.isDefined(p);
@@ -1032,7 +1032,7 @@
         ph: 'S', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -1056,7 +1056,7 @@
         ph: 'S', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -1078,7 +1078,7 @@
       {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'S', id: 72} // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -1114,7 +1114,7 @@
         tid: 53, ph: 'T', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isUndefined(t);
   });
@@ -1128,7 +1128,7 @@
         ph: 'S', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isUndefined(t);
   });
@@ -1144,7 +1144,7 @@
         ph: 'S', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -1183,7 +1183,7 @@
         ph: 'S', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isUndefined(t);
     assert.isTrue(m.hasImportWarnings);
@@ -1208,7 +1208,7 @@
         id: 72, ph: 'e', tts: 60000, use_async_tts: 0}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 3);
@@ -1234,7 +1234,7 @@
         id: 72, ph: 'e', tts: 105000, use_async_tts: 1}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -1258,7 +1258,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -1286,7 +1286,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -1317,7 +1317,7 @@
         cat: 'foo', tid: 53, ph: 'e', id: 74}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 3);
@@ -1373,7 +1373,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     // Perfectly matched events should not produce a warning.
@@ -1431,7 +1431,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 2);
@@ -1465,7 +1465,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     // Unmatched BEGIN should produce a warning.
@@ -1507,7 +1507,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     // Unmatched BEGIN should produce a warning.
@@ -1555,7 +1555,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     // Unmatched END should produce a warning.
@@ -1597,7 +1597,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     // Unmatched END should produce a warning.
@@ -1649,7 +1649,7 @@
         ph: 'e', id: 72}
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
     assert.isDefined(t);
     assert.equal(t.asyncSliceGroup.slices.length, 2);
@@ -1677,7 +1677,7 @@
       {name: 'c', args: {}, pid: 52, ts: 558, cat: 'test', tid: 53, ph: 'P'},
       {name: 'a', args: {}, pid: 52, ts: 568, cat: 'test', tid: 53, ph: 'P'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[52];
     assert.isDefined(p);
     var t = p.threads[53];
@@ -1711,9 +1711,9 @@
       }
     };
 
-    var options = new tv.c.ImportOptions();
+    var options = new tr.ImportOptions();
     options.shiftWorldToZero = false;
-    var m = new tv.c.TraceModel(eventData, options);
+    var m = new tr.Model(eventData, options);
 
     var p = m.processes[1];
     var t = p.threads[2];
@@ -1730,7 +1730,7 @@
       {name: 'b', pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
       {name: 'c', pid: 52, ts: 549, cat: 'test', tid: 53, ph: 'P'}
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var p = m.processes[52];
     assert.isDefined(p);
     var t = p.threads[53];
@@ -1747,7 +1747,7 @@
       {ts: 20000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 20}}, // @suppress longLineCheck
       {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}} // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false);
     assert.equal(m.bounds.min, 10);
     assert.equal(m.bounds.max, 50);
@@ -1791,7 +1791,7 @@
         ]}}
     ];
 
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false);
     var p1 = m.processes[1];
 
@@ -1829,7 +1829,7 @@
         ]}}
     ];
 
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false);
     var p1 = m.processes[1];
 
@@ -1850,7 +1850,7 @@
       {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'LayerImpl', args: {}} // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false);
     var p1 = m.processes[1];
     assert.equal(m.importWarnings.length, 0);
@@ -1872,7 +1872,7 @@
       {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false);
     var p1 = m.processes[1];
 
@@ -1899,7 +1899,7 @@
       {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false);
     var p1 = m.processes[1];
 
@@ -1925,16 +1925,16 @@
         ]}}}
     ];
 
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([events], false);
     var p1 = m.processes[1];
 
     var sA = p1.objects.getSnapshotAt('0x1000', 15);
     assert.isTrue(sA.args.x instanceof Array);
     assert.equal(sA.args.x.length, 3);
-    assert.isTrue(sA.args.x[0] instanceof tv.c.trace_model.ObjectSnapshot);
-    assert.isTrue(sA.args.x[1] instanceof tv.c.trace_model.ObjectSnapshot);
-    assert.isTrue(sA.args.x[2] instanceof tv.c.trace_model.ObjectSnapshot);
+    assert.isTrue(sA.args.x[0] instanceof tr.model.ObjectSnapshot);
+    assert.isTrue(sA.args.x[1] instanceof tr.model.ObjectSnapshot);
+    assert.isTrue(sA.args.x[2] instanceof tr.model.ObjectSnapshot);
   });
 
   test('importDoesNotMutateEventList', function() {
@@ -1955,21 +1955,21 @@
     // The A type family exists to mutate the args list provided to
     // snapshots.
     function ASnapshot() {
-      tv.c.trace_model.ObjectSnapshot.apply(this, arguments);
+      tr.model.ObjectSnapshot.apply(this, arguments);
       this.args.foo = 7;
     }
     ASnapshot.prototype = {
-      __proto__: tv.c.trace_model.ObjectSnapshot.prototype
+      __proto__: tr.model.ObjectSnapshot.prototype
     };
 
     // Import event while the A types are registered, causing the
     // arguments of the snapshots to be mutated.
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     try {
-      tv.c.trace_model.ObjectSnapshot.register(ASnapshot, {typeName: 'a'});
+      tr.model.ObjectSnapshot.register(ASnapshot, {typeName: 'a'});
       m.importTraces([events], false);
     } finally {
-      tv.c.trace_model.ObjectSnapshot.unregister(ASnapshot);
+      tr.model.ObjectSnapshot.unregister(ASnapshot);
     }
     assert.isFalse(m.hasImportWarnings);
 
@@ -1997,7 +1997,7 @@
       { id: 72, pid: 52, tid: 53, ts: 582, ph: 'E', args: {} }  // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
 
     assert.isDefined(t);
@@ -2033,6 +2033,110 @@
     assert.deepEqual(f1.endSlice.inFlowEvents, [f1]);
   });
 
+  test('importOldFlowEventBindtoNext', function() {
+    // Old trace format without event.bp, and event.cat doesn't contain input
+    var events = [
+      { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', 'dur': 100},   // @suppress longLineCheck
+      { name: 'flow', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {}},  // @suppress longLineCheck
+
+      { name: 'flow', cat: 'foo', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', args: {}},   // @suppress longLineCheck
+      { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, 'dur': 100},   // @suppress longLineCheck
+      { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, 'dur': 1000}   // @suppress longLineCheck
+
+    ];
+
+    var m = new tr.Model(events, false, false);
+
+    assert.equal(m.flowEvents.length, 1);
+
+    var f0 = m.flowEvents[0];
+
+    assert.equal(f0.title, 'flow');
+    assert.equal(f0.category, 'foo');
+    assert.equal(f0.id, 72);
+    assert.equal(f0.start, .548);
+    assert.closeTo(32 / 1000, f0.duration, 1e-5);
+    assert.equal(f0.startSlice.title, 'slice1');
+    assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+    assert.equal(f0.endSlice.title, 'slice3');
+    assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+  });
+
+  test('importOldFlowEventBindtoParent', function() {
+    // Old trace format without event.bp, but event.cat contains input
+    var events = [
+      { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', 'dur': 100},   // @suppress longLineCheck
+      { name: 'flow', cat: 'input', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {}},  // @suppress longLineCheck
+
+      { name: 'flow', cat: 'input', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', args: {}},   // @suppress longLineCheck
+      { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, 'dur': 100},   // @suppress longLineCheck
+      { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, 'dur': 1000}   // @suppress longLineCheck
+
+    ];
+
+    var m = new tr.Model(events, false, false);
+
+    assert.equal(m.flowEvents.length, 1);
+
+    var f0 = m.flowEvents[0];
+
+    assert.equal(f0.title, 'flow');
+    assert.equal(f0.category, 'input');
+    assert.equal(f0.id, 72);
+    assert.equal(f0.start, .548);
+    assert.closeTo(32 / 1000, f0.duration, 1e-5);
+    assert.equal(f0.startSlice.title, 'slice1');
+    assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+    assert.equal(f0.endSlice.title, 'slice2');
+    assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+  });
+
+  test('importNewFlowEventBindtoParent', function() {
+    // New trace format with event.bp
+    var events = [
+      { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', 'dur': 100},   // @suppress longLineCheck
+      { name: 'flow', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', bp: 'e', args: {}},  // @suppress longLineCheck
+
+      { name: 'flow', cat: 'foo', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', bp: 'e', args: {}},   // @suppress longLineCheck
+      { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, 'dur': 100},   // @suppress longLineCheck
+      { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, 'dur': 1000}   // @suppress longLineCheck
+
+    ];
+
+    var m = new tr.Model(events, false, false);
+
+    assert.equal(m.flowEvents.length, 1);
+
+    var f0 = m.flowEvents[0];
+
+    assert.equal(f0.title, 'flow');
+    assert.equal(f0.category, 'foo');
+    assert.equal(f0.id, 72);
+    assert.equal(f0.start, .548);
+    assert.closeTo(32 / 1000, f0.duration, 1e-5);
+    assert.equal(f0.startSlice.title, 'slice1');
+    assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+    assert.equal(f0.endSlice.title, 'slice2');
+    assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+  });
+
+  test('importNewFlowEventWithInvalidBindingPoint', function() {
+    // New trace format with event.bp, which however !== 'e'
+    var events = [
+      { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', 'dur': 100},   // @suppress longLineCheck
+      { name: 'flow', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', bp: 'z', args: {}},  // @suppress longLineCheck
+
+      { name: 'flow', cat: 'foo', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', bp: 'z', args: {}},   // @suppress longLineCheck
+      { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, 'dur': 100},   // @suppress longLineCheck
+      { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, 'dur': 1000}   // @suppress longLineCheck
+
+    ];
+
+    var m = new tr.Model(events, false, false);
+
+    assert.equal(m.flowEvents.length, 0);
+  });
+
   // This test creates a flow event that stops on the same timestamp that
   // the 'X' event which it triggers begins.
   test('importFlowEventOverlaps', function() {
@@ -2045,7 +2149,7 @@
       { name: 'RunTask', cat: 'foo', pid: 70, tid: 71, ts: 580, ph: 'X', args: {'src_func': 'PostRunTask'}, 'dur': 1000}   // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(events, false, false);
+    var m = new tr.Model(events, false, false);
     var startT = m.processes[52].threads[53];
     var endT = m.processes[70].threads[71];
 
@@ -2093,7 +2197,7 @@
     ];
 
     var expected = [0.4, 0.0, 0.412];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.flowIntervalTree.size, 3);
 
     var order = m.flowEvents.map(function(x) { return x.start });
@@ -2108,7 +2212,7 @@
       { name: 'c', args: {}, pid: 52, ts: 740, cat: 'baz', tid: 53, ph: 'X' }
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[52];
     assert.isDefined(p);
@@ -2146,7 +2250,7 @@
       { name: 'c', args: {}, pid: 52, ts: 740, cat: 'baz', tid: 53, ph: 'X', tts: 115 }  // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     assert.equal(m.numProcesses, 1);
     var p = m.processes[52];
     assert.isDefined(p);
@@ -2187,7 +2291,7 @@
       { name: 'b', args: {}, pid: 52, ts: 244654227095, dur: 36045, cat: 'foo', tid: 53, ph: 'X' }  // @suppress longLineCheck
     ];
 
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var t = m.processes[52].threads[53];
 
     var sA = findSliceNamed(t.sliceGroup, 'a');
@@ -2239,9 +2343,9 @@
       }
     };
 
-    var options = new tv.c.ImportOptions();
+    var options = new tr.ImportOptions();
     options.shiftWorldToZero = false;
-    var m = new tv.c.TraceModel(eventData, options);
+    var m = new tr.Model(eventData, options);
 
     var p = m.processes[1];
     var t = p.threads[2];
@@ -2268,7 +2372,7 @@
 
     events.push({name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 1000, ph: 'F', args: {'seq': 1001}});  // @suppress longLineCheck
 
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t = m.processes[52].threads[53];
 
     assert.equal(t.asyncSliceGroup.slices.length, 1);
@@ -2327,11 +2431,11 @@
         }
       ]
     };
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     assert.isDefined(m.kernel.cpus[0]);
     assert.equal(m.getAllThreads().length, 1);
 
-    assert.equal(tv.b.dictionaryKeys(m.stackFrames).length, 4);
+    assert.equal(tr.b.dictionaryKeys(m.stackFrames).length, 4);
     assert.equal(m.samples.length, 3);
 
     var t1 = m.processes[1].threads[1];
@@ -2415,13 +2519,13 @@
         }
       }
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p1 = m.getProcess(42);
     var p2 = m.getProcess(43);
     assert.isDefined(p1);
     assert.isDefined(p2);
 
-    // Check that TraceModel and Process objects contain the right dumps.
+    // Check that Model and Process objects contain the right dumps.
     assert.equal(m.globalMemoryDumps.length, 2);
     assert.equal(p1.memoryDumps.length, 2);
     assert.equal(p2.memoryDumps.length, 1);
@@ -2471,7 +2575,7 @@
         }
       }
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.getProcess(42);
     var d = p.memoryDumps[0];
 
@@ -2504,8 +2608,11 @@
                   mf: '[stack:20310]',
                   bs: {
                     pss: '9e',
-                    prv: '60',
-                    shr: '50'
+                    pc: '40',
+                    pd: '20',
+                    sc: '100',
+                    sd: '0',
+                    sw: '50'
                   }
                 },
                 {
@@ -2515,8 +2622,8 @@
                   mf: '/dev/ashmem/dalvik',
                   bs: {
                     pss: 'cd',
-                    prv: 'cd',
-                    shr: '0'
+                    pd: 'cd',
+                    sw: '0'
                   }
                 }
               ]
@@ -2525,7 +2632,7 @@
         }
       }
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.getProcess(42);
     var d = p.memoryDumps[0];
 
@@ -2537,10 +2644,12 @@
     assert.equal(vr1.protectionFlags, 6);
     assert.equal(vr1.protectionFlagsToString, 'rw-');
     assert.equal(vr1.mappedFile, '[stack:20310]');
-    assert.equal(vr1.byteStats.privateResident, 96);
-    assert.equal(vr1.byteStats.sharedResident, 80);
+    assert.equal(vr1.byteStats.privateCleanResident, 64);
+    assert.equal(vr1.byteStats.privateDirtyResident, 32);
+    assert.equal(vr1.byteStats.sharedCleanResident, 256);
+    assert.equal(vr1.byteStats.sharedDirtyResident, 0);
     assert.equal(vr1.byteStats.proportionalResident, 158);
-    assert.equal(vr1.byteStats.totalResident, 176);
+    assert.equal(vr1.byteStats.swapped, 80);
 
     var vr2 = d.mostRecentVmRegions[1];
     assert.equal(vr2.startAddress, 848);
@@ -2548,10 +2657,12 @@
     assert.equal(vr2.protectionFlags, 5);
     assert.equal(vr2.protectionFlagsToString, 'r-x');
     assert.equal(vr2.mappedFile, '/dev/ashmem/dalvik');
-    assert.equal(vr2.byteStats.privateResident, 205);
-    assert.equal(vr2.byteStats.sharedResident, 0);
     assert.equal(vr2.byteStats.proportionalResident, 205);
-    assert.equal(vr2.byteStats.totalResident, 205);
+    assert.isUndefined(vr2.byteStats.privateCleanResident);
+    assert.equal(vr2.byteStats.privateDirtyResident, 205);
+    assert.isUndefined(vr2.byteStats.sharedCleanResident);
+    assert.isUndefined(vr2.byteStats.sharedDirtyResident);
+    assert.equal(vr2.byteStats.swapped, 0);
 
     assert.equal(d.totalResidentBytes, 0);
     assert.lengthOf(d.memoryAllocatorDumps, 0);
@@ -2580,7 +2691,7 @@
                     type: 'scalar', units: 'objects', value: '2f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '1000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '4000'}
+                  size: {type: 'scalar', units: 'bytes', value: '4000'}
                 }
               },
               'oilpan/heap1': {
@@ -2590,7 +2701,7 @@
                     type: 'scalar', units: 'objects', value: '3f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '3000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '4000'}
+                  size: {type: 'scalar', units: 'bytes', value: '4000'}
                 }
               },
               'oilpan/heap2': {
@@ -2600,7 +2711,7 @@
                     type: 'scalar', units: 'objects', value: '4f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '4000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '4000'}
+                  size: {type: 'scalar', units: 'bytes', value: '4000'}
                 }
               },
               'oilpan/heap2/bucket1': {
@@ -2611,7 +2722,7 @@
                     type: 'scalar', units: 'objects', value: '1f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '2000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '2000'}
+                  size: {type: 'scalar', units: 'bytes', value: '2000'}
                 }
               },
               'v8': {
@@ -2621,7 +2732,7 @@
                     type: 'scalar', units: 'objects', value: '5f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '5000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '6000'}
+                  size: {type: 'scalar', units: 'bytes', value: '6000'}
                 }
               }
             }
@@ -2629,7 +2740,7 @@
         }
       }
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.getProcess(42);
     var d = p.memoryDumps[0];
 
@@ -2643,7 +2754,7 @@
     assert.include(d.memoryAllocatorDumps, v8Root);
 
     assert.equal(oilpanRoot.attributes['objects_count'].value, 47);
-    assert.equal(oilpanRoot.attributes['outer_size'].value, 16384);
+    assert.equal(oilpanRoot.attributes['size'].value, 16384);
     assert.equal(oilpanRoot.attributes['inner_size'].value, 4096);
     assert.equal(oilpanRoot.children.length, 2);
 
@@ -2653,7 +2764,7 @@
     assert.equal(oilpanBucket1.fullName, 'oilpan/heap2/bucket1');
     assert.equal(oilpanBucket1.name, 'bucket1');
     assert.equal(oilpanBucket1.attributes['objects_count'].value, 31);
-    assert.equal(oilpanBucket1.attributes['outer_size'].value, 8192);
+    assert.equal(oilpanBucket1.attributes['size'].value, 8192);
     assert.equal(oilpanBucket1.attributes['inner_size'].value, 8192);
     assert.equal(oilpanBucket1.children.length, 0);
 
@@ -2692,7 +2803,7 @@
                     type: 'scalar', units: 'objects', value: '3f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '3000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '4000'}
+                  size: {type: 'scalar', units: 'bytes', value: '4000'}
                 }
               },
               'oilpan/heap2/bucket1': {
@@ -2702,7 +2813,7 @@
                     type: 'scalar', units: 'objects', value: '1f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '2000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '2000'}
+                  size: {type: 'scalar', units: 'bytes', value: '2000'}
                 }
               },
               'v8': {
@@ -2712,7 +2823,7 @@
                     type: 'scalar', units: 'objects', value: '5f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '5000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '6000'}
+                  size: {type: 'scalar', units: 'bytes', value: '6000'}
                 }
               }
             }
@@ -2720,7 +2831,7 @@
         }
       }
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.getProcess(42);
     var d = p.memoryDumps[0];
 
@@ -2734,7 +2845,7 @@
     assert.include(d.memoryAllocatorDumps, v8Root);
 
     assert.equal(oilpanRoot.attributes['objects_count'].value, 94);
-    assert.equal(oilpanRoot.attributes['outer_size'].value, 24576);
+    assert.equal(oilpanRoot.attributes['size'].value, 24576);
     assert.equal(oilpanRoot.attributes['inner_size'].value, 20480);
     assert.equal(oilpanRoot.children.length, 2);
 
@@ -2744,7 +2855,7 @@
     assert.equal(oilpanBucket1.fullName, 'oilpan/heap2/bucket1');
     assert.equal(oilpanBucket1.name, 'bucket1');
     assert.equal(oilpanBucket1.attributes['objects_count'].value, 31);
-    assert.equal(oilpanBucket1.attributes['outer_size'].value, 8192);
+    assert.equal(oilpanBucket1.attributes['size'].value, 8192);
     assert.equal(oilpanBucket1.attributes['inner_size'].value, 8192);
     assert.equal(oilpanBucket1.children.length, 0);
 
@@ -2783,7 +2894,7 @@
                     type: 'scalar', units: 'objects', value: '3f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '3000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '4000'},
+                  size: {type: 'scalar', units: 'bytes', value: '4000'},
                   weather: {type: 'string', units: '', value: 'rainy'}
                 }
               },
@@ -2794,7 +2905,7 @@
                     type: 'scalar', units: 'objects', value: '1f'
                   },
                   inner_size: {type: 'scalar', units: 'bytes', value: '2000'},
-                  outer_size: {type: 'scalar', units: 'bytes', value: '2000'},
+                  size: {type: 'scalar', units: 'bytes', value: '2000'},
                   weather: {type: 'string', units: '', value: 'sunny'}
                 }
               }
@@ -2803,7 +2914,7 @@
         }
       }
     ];
-    var m = new tv.c.TraceModel(events, false);
+    var m = new tr.Model(events, false);
     var p = m.getProcess(42);
     var gmd = m.globalMemoryDumps[0];
     var pmd = p.memoryDumps[0];
@@ -2824,7 +2935,7 @@
     assert.include(gmd.memoryAllocatorDumps, sharedBitmapManager);
 
     assert.equal(sharedBitmapManager.attributes['objects_count'].value, 31);
-    assert.equal(sharedBitmapManager.attributes['outer_size'].value, 8192);
+    assert.equal(sharedBitmapManager.attributes['size'].value, 8192);
     assert.equal(sharedBitmapManager.attributes['inner_size'].value, 8192);
     assert.isUndefined(sharedBitmapManager.attributes['weather']);
     assert.lengthOf(sharedBitmapManager.children, 1);
@@ -2836,7 +2947,7 @@
     assert.strictEqual(bitmap2.parent, sharedBitmapManager);
 
     assert.equal(bitmap2.attributes['objects_count'].value, 31);
-    assert.equal(bitmap2.attributes['outer_size'].value, 8192);
+    assert.equal(bitmap2.attributes['size'].value, 8192);
     assert.equal(bitmap2.attributes['inner_size'].value, 8192);
     assert.equal(bitmap2.attributes['weather'].value, 'sunny');
     assert.lengthOf(bitmap2.children, 0);
@@ -2852,7 +2963,7 @@
     assert.isUndefined(tileManagerRoot.parent);
 
     assert.equal(tileManagerRoot.attributes['objects_count'].value, 63);
-    assert.equal(tileManagerRoot.attributes['outer_size'].value, 16384);
+    assert.equal(tileManagerRoot.attributes['size'].value, 16384);
     assert.equal(tileManagerRoot.attributes['inner_size'].value, 12288);
     assert.isUndefined(tileManagerRoot.attributes['weather']);
     assert.lengthOf(tileManagerRoot.children, 1);
@@ -2864,7 +2975,7 @@
     assert.strictEqual(tile1.parent, tileManagerRoot);
 
     assert.equal(tile1.attributes['objects_count'].value, 63);
-    assert.equal(tile1.attributes['outer_size'].value, 16384);
+    assert.equal(tile1.attributes['size'].value, 16384);
     assert.equal(tile1.attributes['inner_size'].value, 12288);
     assert.equal(tile1.attributes['weather'].value, 'rainy');
     assert.lengthOf(tile1.children, 0);
@@ -3003,7 +3114,7 @@
         }
       }
     ];
-    var model = new tv.c.TraceModel(events, false);
+    var model = new tr.Model(events, false);
     var browserProcess = model.getProcess(42);
     var rendererProcess = model.getProcess(43);
     var gpuProcess = model.getProcess(44);
@@ -3151,9 +3262,9 @@
       }
     };
 
-    var options = new tv.c.ImportOptions();
+    var options = new tr.ImportOptions();
     options.shiftWorldToZero = false;
-    var m = new tv.c.TraceModel(eventData, options);
+    var m = new tr.Model(eventData, options);
 
     var p = m.processes[1];
     var t = p.threads[2];
@@ -3189,9 +3300,9 @@
       }
     };
 
-    var options = new tv.c.ImportOptions();
+    var options = new tr.ImportOptions();
     options.shiftWorldToZero = false;
-    var m = new tv.c.TraceModel(eventData, options);
+    var m = new tr.Model(eventData, options);
 
     var p = m.processes[1];
     var t = p.threads[2];
@@ -3208,8 +3319,8 @@
       {stableId: '52', yPercentOffset: 0.3}];
     var yComponents2 = [{stableId: '52.53', yPercentOffset: 0.7},
       {stableId: '52', yPercentOffset: 0.4}];
-    var location1 = new tv.c.Location(0.1, yComponents1);
-    var location2 = new tv.c.Location(0.2, yComponents2);
+    var location1 = new tr.c.Location(0.1, yComponents1);
+    var location2 = new tr.c.Location(0.2, yComponents2);
 
     var eventData = { traceEvents: [
       {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'}],
@@ -3221,19 +3332,19 @@
           location: location1.toDict()}}
       ]};
 
-    var m = new tv.c.TraceModel(eventData);
+    var m = new tr.Model(eventData);
     var annotations = m.getAllAnnotations();
     assert.equal(annotations.length, 3);
 
-    assert.isTrue(annotations[0] instanceof tv.c.trace_model.XMarkerAnnotation);
+    assert.isTrue(annotations[0] instanceof tr.model.XMarkerAnnotation);
     assert.equal(annotations[0].timestamp, 12);
 
-    assert.isTrue(annotations[1] instanceof tv.c.trace_model.RectAnnotation);
+    assert.isTrue(annotations[1] instanceof tr.model.RectAnnotation);
     assert.deepEqual(annotations[1].startLocation, location1);
     assert.deepEqual(annotations[1].endLocation, location2);
 
     assert.isTrue(
-        annotations[2] instanceof tv.c.trace_model.CommentBoxAnnotation);
+        annotations[2] instanceof tr.model.CommentBoxAnnotation);
     assert.equal(annotations[2].text, 'test');
     assert.deepEqual(annotations[2].location, location1);
   });
diff --git a/trace-viewer/trace_viewer/extras/importer/v8/codemap.html b/trace-viewer/trace_viewer/extras/importer/v8/codemap.html
index 2c46f63..ed44722 100644
--- a/trace-viewer/trace_viewer/extras/importer/v8/codemap.html
+++ b/trace-viewer/trace_viewer/extras/importer/v8/codemap.html
@@ -13,7 +13,7 @@
 /**
  * @fileoverview Map addresses to dynamically created functions.
  */
-tv.exportTo('tv.e.importer.v8', function() {
+tr.exportTo('tr.e.importer.v8', function() {
   /**
    * Constructs a mapper that maps addresses into code entries.
    *
@@ -23,22 +23,22 @@
     /**
      * Dynamic code entries. Used for JIT compiled code.
      */
-    this.dynamics_ = new tv.e.importer.v8.SplayTree();
+    this.dynamics_ = new tr.e.importer.v8.SplayTree();
 
     /**
      * Name generator for entries having duplicate names.
      */
-    this.dynamicsNameGen_ = new tv.e.importer.v8.CodeMap.NameGenerator();
+    this.dynamicsNameGen_ = new tr.e.importer.v8.CodeMap.NameGenerator();
 
     /**
      * Static code entries. Used for statically compiled code.
      */
-    this.statics_ = new tv.e.importer.v8.SplayTree();
+    this.statics_ = new tr.e.importer.v8.SplayTree();
 
     /**
      * Libraries entries. Used for the whole static code libraries.
      */
-    this.libraries_ = new tv.e.importer.v8.SplayTree();
+    this.libraries_ = new tr.e.importer.v8.SplayTree();
 
     /**
      * Map of memory pages occupied with static code.
@@ -231,7 +231,7 @@
    * @constructor
    */
   CodeMap.CodeEntry = function(size, opt_name) {
-    this.id = tv.b.GUID.allocate();
+    this.id = tr.b.GUID.allocate();
     this.size = size;
     this.name = opt_name || '';
     this.nameUpdated_ = false;
diff --git a/trace-viewer/trace_viewer/extras/importer/v8/log_reader.html b/trace-viewer/trace_viewer/extras/importer/v8/log_reader.html
index a6c987f..57b531a 100644
--- a/trace-viewer/trace_viewer/extras/importer/v8/log_reader.html
+++ b/trace-viewer/trace_viewer/extras/importer/v8/log_reader.html
@@ -11,7 +11,7 @@
 /**
  * @fileoverview Log Reader is used to process log file produced by V8.
  */
-tv.exportTo('tv.e.importer.v8', function() {
+tr.exportTo('tr.e.importer.v8', function() {
   /**
    * Creates a CSV lines parser.
    */
diff --git a/trace-viewer/trace_viewer/extras/importer/v8/splaytree.html b/trace-viewer/trace_viewer/extras/importer/v8/splaytree.html
index 61df71a..5bd0eaa 100644
--- a/trace-viewer/trace_viewer/extras/importer/v8/splaytree.html
+++ b/trace-viewer/trace_viewer/extras/importer/v8/splaytree.html
@@ -11,7 +11,7 @@
 /**
  * @fileoverview Splay tree used by CodeMap.
  */
-tv.exportTo('tv.e.importer.v8', function() {
+tr.exportTo('tr.e.importer.v8', function() {
   /**
    * Constructs a Splay tree.  A splay tree is a self-balancing binary
    * search tree with the additional property that recently accessed
diff --git a/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer.html b/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer.html
index 547811d..9a57b60 100644
--- a/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer.html
@@ -8,9 +8,9 @@
 <link rel="import" href="/base/ui/color_scheme.html">
 <link rel="import" href="/extras/importer/v8/log_reader.html">
 <link rel="import" href="/extras/importer/v8/codemap.html">
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/trace_model/slice.html">
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/slice.html">
 
 <script>
 
@@ -19,8 +19,8 @@
 /**
  * @fileoverview V8LogImporter imports v8.log files into the provided model.
  */
-tv.exportTo('tv.e.importer.v8', function() {
-  var Importer = tv.c.importer.Importer;
+tr.exportTo('tr.e.importer.v8', function() {
+  var Importer = tr.importer.Importer;
 
   function V8LogImporter(model, eventData) {
     this.importPriority = 3;
@@ -28,11 +28,11 @@
 
     this.logData_ = eventData;
 
-    this.code_map_ = new tv.e.importer.v8.CodeMap();
+    this.code_map_ = new tr.e.importer.v8.CodeMap();
     this.v8_timer_thread_ = undefined;
     this.v8_thread_ = undefined;
 
-    this.root_stack_frame_ = new tv.c.trace_model.StackFrame(
+    this.root_stack_frame_ = new tr.model.StackFrame(
         undefined, 'v8-root-stack-frame',
         'v8-root-stack-frame', 'v8-root-stack-frame', 0);
 
@@ -82,8 +82,8 @@
       if (args === undefined) return;
       start /= 1000;  // Convert to milliseconds.
       length /= 1000;
-      var colorId = tv.b.ui.getColorIdForGeneralPurposeString(name);
-      var slice = new tv.c.trace_model.Slice('v8', name, colorId, start,
+      var colorId = tr.b.ui.getColorIdForGeneralPurposeString(name);
+      var slice = new tr.model.Slice('v8', name, colorId, start,
           args, length);
       this.v8_timer_thread_.sliceGroup.pushSlice(slice);
     },
@@ -101,7 +101,7 @@
     },
 
     processCodeCreateEvent_: function(type, kind, address, size, name) {
-      var code_entry = new tv.e.importer.v8.CodeMap.CodeEntry(size, name);
+      var code_entry = new tr.e.importer.v8.CodeMap.CodeEntry(size, name);
       code_entry.kind = kind;
       this.code_map_.addCode(address, code_entry);
     },
@@ -115,7 +115,7 @@
     },
 
     processSharedLibrary_: function(name, start, end) {
-      var code_entry = new tv.e.importer.v8.CodeMap.CodeEntry(
+      var code_entry = new tr.e.importer.v8.CodeMap.CodeEntry(
           end - start, name);
       code_entry.kind = -3;  // External code kind.
       for (var i = 0; i < kV8BinarySuffixes.length; i++) {
@@ -162,10 +162,10 @@
           var childFrame = findChildWithEntryID(lastStackFrame, entryID);
           if (childFrame === undefined) {
             var entryName = entry ? entry.name : 'Unknown';
-            lastStackFrame = new tv.c.trace_model.StackFrame(
-                lastStackFrame, 'v8sf-' + tv.b.GUID.allocate(),
+            lastStackFrame = new tr.model.StackFrame(
+                lastStackFrame, 'v8sf-' + tr.b.GUID.allocate(),
                 'v8', entryName,
-                tv.b.ui.getColorIdForGeneralPurposeString(entryName));
+                tr.b.ui.getColorIdForGeneralPurposeString(entryName));
             lastStackFrame.entryID = entryID;
             this.model_.addStackFrame(lastStackFrame);
           } else {
@@ -177,16 +177,16 @@
         var pcEntryID = 'v8pc-' + (pcEntry ? pcEntry.id : 'Unknown');
         if (this.model_.stackFrames[pcEntryID] === undefined) {
           var pcEntryName = pcEntry ? pcEntry.name : 'Unknown';
-          lastStackFrame = new tv.c.trace_model.StackFrame(
+          lastStackFrame = new tr.model.StackFrame(
               undefined, pcEntryID,
               'v8', pcEntryName,
-              tv.b.ui.getColorIdForGeneralPurposeString(pcEntryName));
+              tr.b.ui.getColorIdForGeneralPurposeString(pcEntryName));
           this.model_.addStackFrame(lastStackFrame);
         }
         lastStackFrame = this.model_.stackFrames[pcEntryID];
       }
 
-      var sample = new tv.c.trace_model.Sample(
+      var sample = new tr.model.Sample(
           undefined, this.v8_thread_, 'V8 PC',
           start, lastStackFrame, 1);
       this.model_.samples.push(sample);
@@ -210,7 +210,7 @@
      * model_.
      */
     importEvents: function() {
-      var logreader = new tv.e.importer.v8.LogReader(
+      var logreader = new tr.e.importer.v8.LogReader(
           { 'timer-event' : {
             parsers: [null, parseInt, parseInt],
             processor: this.processTimerEvent_.bind(this)
@@ -277,8 +277,8 @@
       function addSlices(slices, thread) {
         for (var i = 0; i < slices.length; i++) {
           var duration = slices[i].end - slices[i].start;
-          var slice = new tv.c.trace_model.Slice('v8', slices[i].name,
-              tv.b.ui.getColorIdForGeneralPurposeString(slices[i].name),
+          var slice = new tr.model.Slice('v8', slices[i].name,
+              tr.b.ui.getColorIdForGeneralPurposeString(slices[i].name),
               slices[i].start, {}, duration);
           thread.sliceGroup.pushSlice(slice);
           addSlices(slices[i].children, thread);
@@ -288,7 +288,7 @@
     }
   };
 
-  tv.c.importer.Importer.register(V8LogImporter);
+  tr.importer.Importer.register(V8LogImporter);
 
   return {
     V8LogImporter: V8LogImporter
diff --git a/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer_test.html b/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer_test.html
index 08fb758..8422e27 100644
--- a/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer_test.html
+++ b/trace-viewer/trace_viewer/extras/importer/v8/v8_log_importer_test.html
@@ -12,14 +12,14 @@
 
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var V8LogImporter = tv.e.importer.v8.V8LogImporter;
+tr.b.unittest.testSuite(function() {
+  var V8LogImporter = tr.e.importer.v8.V8LogImporter;
 
   test('tickEventInSharedLibrary', function() {
     var lines = [
       'shared-library,"/usr/lib/libc++.1.dylib",0x99d8aae0,0x99dce729',
       'tick,0x99d8aae4,12158,0,0x0,5'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var t = p.findAllThreadsNamed('V8')[0];
     assert.equal(t.samples.length, 1);
@@ -33,7 +33,7 @@
       'shared-library,"/usr/lib/libc++.1.dylib",0x99d8aae0,0x99dce729',
       'code-creation,Stub,2,0x5b60ce80,1259,"StringAddStub"',
       'tick,0x5b60ce84,12158,0,0x0,5'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var threads = p.findAllThreadsNamed('V8');
     var t = threads[0];
@@ -46,7 +46,7 @@
       'shared-library,"/usr/lib/libc++.1.dylib",0x99d8aae0,0x99dce729',
       'code-creation,Stub,2,0x5b60ce80,1259,"StringAddStub"',
       'tick,0x4,0xbff02f08,12158,0,0x0,5'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var threads = p.findAllThreadsNamed('V8');
     var t = threads[0];
@@ -58,7 +58,7 @@
     var lines = [
       'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
       'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var t = p.findAllThreadsNamed('V8')[0];
     assert.equal(t.samples.length, 1);
@@ -72,7 +72,7 @@
       'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
       'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304',
       'tick,0x7fd2a534,536213,0,0x81d8d080,0,0x2905d304'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var t = p.findAllThreadsNamed('V8')[0];
     assert.equal(t.samples.length, 2);
@@ -94,7 +94,7 @@
       'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
       'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304,0x2904d6e8',
       'tick,0x7fd2a534,536213,0,0x81d8d080,0,0x2905d304,0x2904d6e8'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var t = p.findAllThreadsNamed('V8')[0];
     assert.equal(t.samples.length, 2);
@@ -127,7 +127,7 @@
       'tick,0x7fd7f75c,518328,0,0x81d86da8,2,0x2904d6e8',
       'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304,0x2904d6e8',
       'tick,0x7fd2a534,536213,0,0x81d8d080,0,0x2905d304,0x2904d6e8'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var threads = p.findAllThreadsNamed('V8');
 
@@ -168,7 +168,7 @@
       'tick,0xb6f51d30,794049,0,0xb6f7b368,2,0x2906a914',
       'tick,0xb6f51d30,799146,0,0xb6f7b368,0,0x2906a914'
     ];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var threads = p.findAllThreadsNamed('V8');
     var t = threads[0];
@@ -214,7 +214,7 @@
 
   test('timerEventSliceCreation', function() {
     var lines = ['timer-event,"V8.External",38189483,3'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     var p = m.processes[-32];
     var threads = p.findAllThreadsNamed('V8 Timers');
     assert.isDefined(threads);
@@ -225,7 +225,7 @@
 
   test('processThreadCreation', function() {
     var lines = ['timer-event,"V8.External",38189483,3'];
-    var m = new tv.c.TraceModel(lines.join('\n'), false);
+    var m = new tr.Model(lines.join('\n'), false);
     assert.isDefined(m);
     var p = m.processes[-32];
     assert.isDefined(p);
diff --git a/trace-viewer/trace_viewer/extras/importer/zip_importer.html b/trace-viewer/trace_viewer/extras/importer/zip_importer.html
index 867b983..b63a3bb 100644
--- a/trace-viewer/trace_viewer/extras/importer/zip_importer.html
+++ b/trace-viewer/trace_viewer/extras/importer/zip_importer.html
@@ -7,8 +7,8 @@
 
 <link rel="import" href="/extras/importer/jszip.html">
 <link rel="import" href="/extras/importer/gzip_importer.html">
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
@@ -17,8 +17,8 @@
  * @fileoverview ZipImporter inflates zip compressed data and passes it along
  * to an actual importer.
  */
-tv.exportTo('tv.e.importer', function() {
-  var Importer = tv.c.importer.Importer;
+tr.exportTo('tr.e.importer', function() {
+  var Importer = tr.importer.Importer;
 
   function ZipImporter(model, eventData) {
     if (eventData instanceof ArrayBuffer)
@@ -58,7 +58,7 @@
     }
   };
 
-  tv.c.importer.Importer.register(ZipImporter);
+  tr.importer.Importer.register(ZipImporter);
 
   return {
     ZipImporter: ZipImporter
diff --git a/trace-viewer/trace_viewer/extras/net/net.html b/trace-viewer/trace_viewer/extras/net/net.html
index d92bf0b..44a2f75 100644
--- a/trace-viewer/trace_viewer/extras/net/net.html
+++ b/trace-viewer/trace_viewer/extras/net/net.html
@@ -5,4 +5,4 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/extras/net/net_async_slice.html">
\ No newline at end of file
+<link rel="import" href="/extras/net/net_async_slice.html">
diff --git a/trace-viewer/trace_viewer/extras/net/net_async_slice.html b/trace-viewer/trace_viewer/extras/net/net_async_slice.html
index 0cbe7b8..54e2d14 100644
--- a/trace-viewer/trace_viewer/extras/net/net_async_slice.html
+++ b/trace-viewer/trace_viewer/extras/net/net_async_slice.html
@@ -4,13 +4,13 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/core/trace_model/async_slice.html">
+<link rel="import" href="/model/async_slice.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.net', function() {
-  var AsyncSlice = tv.c.trace_model.AsyncSlice;
+tr.exportTo('tr.e.net', function() {
+  var AsyncSlice = tr.model.AsyncSlice;
 
   function NetAsyncSlice() {
     AsyncSlice.apply(this, arguments);
diff --git a/trace-viewer/trace_viewer/extras/net/net_async_slice_test.html b/trace-viewer/trace_viewer/extras/net/net_async_slice_test.html
index 30e3e55..bfb13c4 100644
--- a/trace-viewer/trace_viewer/extras/net/net_async_slice_test.html
+++ b/trace-viewer/trace_viewer/extras/net/net_async_slice_test.html
@@ -6,14 +6,15 @@
 -->
 
 <link rel="import" href="/extras/net/net.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
+<link rel="import" href="/model/model.html">
+
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var AsyncSlice = tv.c.trace_model.AsyncSlice;
-  var NetAsyncSlice = tv.e.net.NetAsyncSlice;
+tr.b.unittest.testSuite(function() {
+  var AsyncSlice = tr.model.AsyncSlice;
+  var NetAsyncSlice = tr.e.net.NetAsyncSlice;
 
   test('basic', function() {
     var s = new NetAsyncSlice('netlog', 'HTTP_STREAM_JOB', 7, 0, {});
@@ -29,7 +30,7 @@
       {name: 'HTTP_STREAM_JOB', args: {}, pid: 1, ts: 100, cat: 'netlog', tid: 2, ph: 'b', id: 71}, // @suppress longLineCheck
       {name: 'HTTP_STREAM_JOB', args: {}, pid: 1, ts: 200, cat: 'netlog', tid: 2, ph: 'e', id: 71} // @suppress longLineCheck
     ];
-    var m = new tv.c.TraceModel(events);
+    var m = new tr.Model(events);
     var t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
     assert.equal(t2.asyncSliceGroup.length, 1);
     assert.instanceOf(t2.asyncSliceGroup.slices[0], NetAsyncSlice);
diff --git a/trace-viewer/trace_viewer/extras/rail/animation_interaction_record.html b/trace-viewer/trace_viewer/extras/rail/animation_interaction_record.html
new file mode 100644
index 0000000..cd7478b
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/animation_interaction_record.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/extras/rail/rail_interaction_record.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview The Animation phase of RAIL.
+ */
+tr.exportTo('tr.e.rail', function() {
+  function AnimationInteractionRecord(start, duration) {
+    tr.e.rail.RAILInteractionRecord.call(
+        this, 'Animation', 'rail_animate',
+        start, duration);
+  }
+
+  AnimationInteractionRecord.prototype = {
+    __proto__: tr.e.rail.RAILInteractionRecord.prototype,
+
+    get normalizedUserPain() {
+      return 0;
+    },
+
+    get normalizedEfficiency() {
+      return 1;
+    }
+  };
+
+  return {
+    AnimationInteractionRecord: AnimationInteractionRecord
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/extras/rail/idle_interaction_record.html b/trace-viewer/trace_viewer/extras/rail/idle_interaction_record.html
new file mode 100644
index 0000000..559c76d
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/idle_interaction_record.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/extras/rail/rail_interaction_record.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for trace data Auditors.
+ */
+tr.exportTo('tr.e.rail', function() {
+  function IdleInteractionRecord(start, duration) {
+    tr.e.rail.RAILInteractionRecord.call(
+        this, 'Idle', 'rail_idle',
+        start, duration);
+  }
+
+  IdleInteractionRecord.prototype = {
+    __proto__: tr.e.rail.RAILInteractionRecord.prototype,
+
+    get normalizedUserPain() {
+      return 0;
+    },
+
+    get normalizedEfficiency() {
+      return 1;
+    }
+  };
+
+  return {
+    IdleInteractionRecord: IdleInteractionRecord
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/extras/rail/load_interaction_record.html b/trace-viewer/trace_viewer/extras/rail/load_interaction_record.html
new file mode 100644
index 0000000..6752441
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/load_interaction_record.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/extras/rail/rail_interaction_record.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview The Load phase of RAIL.
+ */
+tr.exportTo('tr.e.rail', function() {
+  function LoadInteractionRecord(start, duration) {
+    tr.e.rail.RAILInteractionRecord.call(
+        this, 'Load', 'rail_load',
+        start, duration);
+  }
+
+  LoadInteractionRecord.prototype = {
+    __proto__: tr.e.rail.RAILInteractionRecord.prototype,
+
+    get normalizedUserPain() {
+      return 0;
+    },
+
+    get normalizedEfficiency() {
+      return 1;
+    }
+  };
+
+  return {
+    LoadInteractionRecord: LoadInteractionRecord
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_interaction_record.html b/trace-viewer/trace_viewer/extras/rail/rail_interaction_record.html
index 6812a5f..3f4b578 100644
--- a/trace-viewer/trace_viewer/extras/rail/rail_interaction_record.html
+++ b/trace-viewer/trace_viewer/extras/rail/rail_interaction_record.html
@@ -7,8 +7,8 @@
 <link rel="import" href="/base/base.html">
 <link rel="import" href="/base/statistics.html">
 <link rel="import" href="/core/auditor.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/extras/audits/utils.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/base/range_utils.html">
 <link rel="import" href="/extras/chrome/chrome_model_helper.html">
 
 <script>
@@ -17,13 +17,17 @@
 /**
  * @fileoverview Base class for trace data Auditors.
  */
-tv.exportTo('tv.e.audits', function() {
-  function RAILInteractionRecord(title, colorId, start, duration) {
-    tv.c.trace_model.InteractionRecord.call(this,
-                                            title, colorId, start, duration);
+tr.exportTo('tr.e.rail', function() {
+
+  function RAILInteractionRecord(title, railTypeName, start, duration) {
+    var colorId = tr.b.ui.getColorIdForReservedName(railTypeName);
+    this.railTypeName_ = railTypeName;
+    tr.model.InteractionRecord.call(this,
+                                    title, colorId, start, duration);
   }
+
   RAILInteractionRecord.prototype = {
-    __proto__: tv.c.trace_model.InteractionRecord.prototype,
+    __proto__: tr.model.InteractionRecord.prototype,
 
     updateArgs: function() {
       var args = {};
@@ -31,7 +35,7 @@
       var layoutSlices = this.associatedEvents.filter(function(event) {
         return event.title === 'FrameView::layout';
       });
-      var timeInLayout = tv.b.Statistics.sum(layoutSlices, function(event) {
+      var timeInLayout = tr.b.Statistics.sum(layoutSlices, function(event) {
         return event.duration;
       });
 
@@ -43,13 +47,48 @@
     },
 
     get railTypeName() {
-      // At some point, we will subclass RAILInteractionRecord, at which point
-      // this will be overridden by the subclasses.
-      return this.title;
+      return this.railTypeName_;
     },
 
+    /**
+     * Returns the overall rail score, from 0 to 1.
+     *
+     * RAILScore for an interaction merges the user's pain with the
+     * efficiency, in order to create a perception-oriented measure
+     * of how users percieve speed during this interaction.
+     *
+     *  0 means a bad user experience.
+     *  1 means a perfect user experience.
+     */
     get railScore() {
-      return this.duration;
+      // TODO(benjhayden, nduca) Better scoring algorithm.
+      var happiness = 1 - this.normalizedUserPain;
+      return this.normalizedEfficiency * happiness;
+    },
+
+    /**
+     * Measures the pain the user experienced, from 0 to 1.
+     *
+     * A user performs an interaction with an expectation in mind.
+     * When we exceed their expectations, we get zero pain.
+     * When we meet their expectations, we get zero pain.
+     * As we exceed their expectations, pain goes up. Maximum pain
+     * is 1.0, aka "Switch to FireFox".
+     */
+    get normalizedUserPain() {
+      throw new Error('Not implemented');
+    },
+
+    /**
+     * Measures the efficiency of the interaction from 0 to 1.
+     *
+     * Efficiency is a notion of how well we used the machine's limited
+     * resources in service of this interaction. If we used it perfectly,
+     * we would get a 1.0. If we used everything that there was to use ---
+     * power, memory, cpu, then we'd get a zero.
+     */
+    get normalizedEfficiency() {
+      throw new Error('Not implemented');
     }
   };
 
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_interaction_record_test.html b/trace-viewer/trace_viewer/extras/rail/rail_interaction_record_test.html
index c5bdc57..fba50de 100644
--- a/trace-viewer/trace_viewer/extras/rail/rail_interaction_record_test.html
+++ b/trace-viewer/trace_viewer/extras/rail/rail_interaction_record_test.html
@@ -9,16 +9,16 @@
 <link rel="import" href="/extras/chrome/chrome_test_utils.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var test_utils = tv.c.test_utils;
+tr.b.unittest.testSuite(function() {
+  var test_utils = tr.c.test_utils;
 
   test('layoutInfo', function() {
-    var model = tv.e.audits.newChromeModel(function(model) {
+    var model = tr.e.audits.newChromeModel(function(model) {
       // TODO(benjhayden): Create
       model.rendererMain.sliceGroup.pushSlice(test_utils.newSliceEx({
         title: 'FrameView::layout',
@@ -27,9 +27,9 @@
       }));
     });
 
-    var modelHelper = new tv.e.audits.ChromeModelHelper(model);
-    var rir = new tv.e.audits.RAILInteractionRecord(
-        'simple', 1, 0, 100, modelHelper);
+    var modelHelper = new tr.e.audits.ChromeModelHelper(model);
+    var rir = new tr.e.rail.RAILInteractionRecord(
+        'simple', 'rail_response', 0, 100);
     rir.associatedEvents.push(model.rendererMain.sliceGroup.slices[0]);
     rir.updateArgs();
 
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_ir_finder.html b/trace-viewer/trace_viewer/extras/rail/rail_ir_finder.html
index afa98f5..7d28b1c 100644
--- a/trace-viewer/trace_viewer/extras/rail/rail_ir_finder.html
+++ b/trace-viewer/trace_viewer/extras/rail/rail_ir_finder.html
@@ -6,10 +6,13 @@
 -->
 <link rel="import" href="/base/base.html">
 <link rel="import" href="/core/auditor.html">
-<link rel="import" href="/core/trace_model/event_info.html">
-<link rel="import" href="/extras/audits/utils.html">
+<link rel="import" href="/model/event_info.html">
+<link rel="import" href="/base/range_utils.html">
 <link rel="import" href="/extras/chrome/chrome_model_helper.html">
-<link rel="import" href="/extras/rail/rail_interaction_record.html">
+<link rel="import" href="/extras/rail/animation_interaction_record.html">
+<link rel="import" href="/extras/rail/idle_interaction_record.html">
+<link rel="import" href="/extras/rail/load_interaction_record.html">
+<link rel="import" href="/extras/rail/response_interaction_record.html">
 
 <script>
 'use strict';
@@ -17,32 +20,32 @@
 /**
  * @fileoverview Base class for trace data Auditors.
  */
-tv.exportTo('tv.e.audits', function() {
+tr.exportTo('tr.e.rail', function() {
   function RAILIRFinder(model, modelHelper) {
     this.model = model;
     this.modelHelper = modelHelper;
   };
 
   RAILIRFinder.supportsModelHelper = function(modelHelper) {
-    return modelHelper.browser !== undefined;
+    return modelHelper.browserHelper !== undefined;
   };
 
   RAILIRFinder.prototype = {
     getAllLatencyEvents: function() {
-      return this.modelHelper.browser.getLatencyEventsInRange(
+      return this.modelHelper.browserHelper.getLatencyEventsInRange(
           this.model.bounds);
     },
 
     getAllFrameEvents: function() {
       var frameEvents = [];
-      if (this.modelHelper.browser) {
-        var fe = this.modelHelper.browser.getFrameEventsInRange(
-            tv.e.audits.IMPL_FRAMETIME_TYPE,
+      if (this.modelHelper.browserHelper) {
+        var fe = this.modelHelper.browserHelper.getFrameEventsInRange(
+            tr.e.audits.IMPL_FRAMETIME_TYPE,
             this.model.bounds);
         frameEvents.push.apply(frameEvents, fe);
       }
-      tv.b.iterItems(this.modelHelper.renderers, function(pid, renderer) {
-        var fe = renderer.getFrameEventsInRange(tv.e.audits.IMPL_FRAMETIME_TYPE,
+      tr.b.iterItems(this.modelHelper.rendererHelpers, function(pid, renderer) {
+        var fe = renderer.getFrameEventsInRange(tr.e.audits.IMPL_FRAMETIME_TYPE,
                                                 this.model.bounds);
         frameEvents.push.apply(frameEvents, fe);
       }, this);
@@ -50,14 +53,6 @@
       return frameEvents;
     },
 
-    getAllLoadAndNetEvents: function() {
-      if (this.modelHelper.browser === undefined)
-        return;
-      var bounds = this.model.bounds;
-      return this.modelHelper.browser.getLoadingEventsInRange(bounds).concat(
-          this.modelHelper.browser.getAllNetworkEventsInRange(bounds));
-    },
-
     getAllGestures: function() {
       var allLatencyEvents = this.getAllLatencyEvents();
 
@@ -86,12 +81,12 @@
         return gesture;
       }
 
-      return tv.e.audits.mergeEvents(
+      return tr.e.audits.mergeExplicitRanges(
           latencyStartPoints, 250, joinStartPointsIntoGesture);
     },
 
     getAllExpectedFlingingRanges: function() {
-      if (this.modelHelper.browser === undefined)
+      if (this.modelHelper.browserHelper === undefined)
         return;
       var ops = [];
       var FLING_OP_START = 'start';
@@ -121,7 +116,7 @@
       });
 
       // Add ops for fling animations.
-      this.modelHelper.browser.getAllAsyncSlicesMatching(function(event) {
+      this.modelHelper.browserHelper.getAllAsyncSlicesMatching(function(event) {
         if (event.title !== 'InputHandlerProxy::HandleGestureFling::started')
           return;
         ops.push({
@@ -191,45 +186,17 @@
       // InputLatency:GestureTapDown/
     },
 
-    findAllInteractionRecords: function() {
-      var rirs = [];
-
-      var gestures = this.getAllGestures();
-      var gestureIRs = gestures.map(function gestureToIR(gesture) {
-        var colorId = tv.b.ui.getColorIdForGeneralPurposeString('mt_input');
-        var ir = new tv.e.audits.RAILInteractionRecord(
-            'railInput', colorId,
-            gesture.expectedStart, gesture.expectedEnd - gesture.expectedStart);
-        ir.associatedEvents.push.apply(
-            ir.associatedEvents,
-            gesture.latencyEvents);
-        return ir;
-      });
-      rirs.push.apply(rirs, gestureIRs);
-
-      var flings = this.getAllExpected60Ranges();
-      var flingIRs = flings.map(function flingToIR(e60r) {
-        var colorId = tv.b.ui.getColorIdForGeneralPurposeString('mt_fling');
-        var ir = new tv.e.audits.RAILInteractionRecord(
-            'railFling', colorId,
-            e60r.expectedStart, e60r.expectedEnd - e60r.expectedStart);
-        return ir;
-      });
-      rirs.push.apply(rirs, flingIRs);
-
-      var allLoadAndNetEvents = this.getAllLoadAndNetEvents();
-
-      var allCommitProvisionalLoad =
-        this.modelHelper.browser.getCommitProvisionalLoadEventsInRange(
+    findLoadInteractionRecords: function() {
+      var commits =
+        this.modelHelper.browserHelper.getCommitProvisionalLoadEventsInRange(
             this.model.bounds);
+      var frames = this.getAllFrameEvents();
 
-      var allFrameEvents = this.getAllFrameEvents();
-
-      allCommitProvisionalLoad.forEach(function(commitLoad, commitLoadIndex) {
-        allFrameEvents.some(function(frame) {
+      commits.forEach(function(commitLoad, commitLoadIndex) {
+        frames.some(function(frame) {
           if ((frame.start > commitLoad.start) &&
-              (frame.parentThread.parent.pid ==
-               commitLoad.parentThread.parent.pid)) {
+              (frame.parentContainer.parent.pid ==
+                  commitLoad.parentContainer.parent.pid)) {
             if (frame.commitProvisionalLoad) return true;
             console.log('commit first frame', commitLoad.start, frame.start,
                 frame.start - commitLoad.start);
@@ -244,53 +211,46 @@
         }
       });
 
-      var allLatencyEvents = this.getAllLatencyEvents();
-      var allFrameAndLatencyEvents = [];
-      allFrameAndLatencyEvents.push.apply(allFrameAndLatencyEvents,
-                                          allFrameEvents);
-      allFrameAndLatencyEvents.push.apply(allFrameAndLatencyEvents,
-                                          allLatencyEvents);
-
-      function mergeEventsIntoIR(title, colorId, events) {
-        var e0 = events[0];
-        var eN = events[events.length - 1];
-        var ir = new tv.c.trace_model.InteractionRecord(
-            title, colorId,
-            e0.start, eN.end - e0.start);
-        ir.events = events;
-        return ir;
-      }
-
-      allCommitProvisionalLoad.forEach(function(commitLoad, commitLoadIndex) {
-        if (!commitLoad.firstFrame) return;
-        var ir = new tv.c.trace_model.InteractionRecord(
-            'CommitToFirstFrame',
-            tv.b.ui.getColorIdForGeneralPurposeString('mt_loading'),
-            commitLoad.start,
-            commitLoad.firstFrame.end - commitLoad.start);
-        ir.events = [commitLoad, commitLoad.firstFrame];
-        if (!ir.args) ir.args = {};
-        ir.args.url = commitLoad.args.url;
-        rirs.push(ir);
+      var lirs = [];
+      commits.forEach(function(commitLoad, commitLoadIndex) {
+        if (!commitLoad.firstFrame)
+          return;
+        lirs.push(new tr.e.rail.LoadInteractionRecord(
+            commitLoad.start, commitLoad.firstFrame.end - commitLoad.start));
       });
+      return lirs;
+    },
 
-      var mergedLoadIRs = tv.e.audits.mergeEvents(
-          allLoadAndNetEvents, 300,
-          mergeEventsIntoIR.bind(
-              undefined, 'Loading/Net',
-              tv.b.ui.getColorIdForGeneralPurposeString('mt_loading')));
-      mergedLoadIRs.forEach(function(loadIR) {
-        if (!loadIR.args) loadIR.args = {};
-        loadIR.args.url = loadIR.events[0].args.URL;
+    findResponseInteractionRecords: function() {
+      return this.getAllGestures().map(function(gesture) {
+        return new tr.e.rail.ResponseInteractionRecord(
+            gesture.expectedStart, gesture.expectedEnd - gesture.expectedStart);
       });
-      rirs.push.apply(rirs, mergedLoadIRs);
+    },
 
-      var mergedFrameIRs = tv.e.audits.mergeEvents(
-          allFrameEvents, 150,
-          mergeEventsIntoIR.bind(
-              undefined, 'Rendering',
-              tv.b.ui.getColorIdForGeneralPurposeString('mt_rendering')));
-      rirs.push.apply(rirs, mergedFrameIRs);
+    findAnimationInteractionRecords: function() {
+      return this.getAllExpected60Ranges().map(function(fling) {
+        return new tr.e.rail.AnimationInteractionRecord(
+            fling.expectedStart, fling.expectedEnd - fling.expectedStart);
+      });
+    },
+
+    findIdleInteractionRecords: function(otherIRs) {
+      var emptyRanges = tr.e.audits.findEmptyRangesBetweenExplicitRanges(
+          otherIRs, this.model.bounds);
+      return emptyRanges.map(function(range) {
+        return new tr.e.rail.IdleInteractionRecord(
+            range.min, range.max - range.min);
+      });
+    },
+
+    findAllInteractionRecords: function() {
+      var rirs = [];
+      rirs.push.apply(rirs, this.findLoadInteractionRecords());
+      rirs.push.apply(rirs, this.findResponseInteractionRecords());
+      rirs.push.apply(rirs, this.findAnimationInteractionRecords());
+      // TODO(benjhayden): Reintroduce this without reintroducing #1020.
+      // rirs.push.apply(rirs, this.findIdleInteractionRecords(rirs));
       return rirs;
     }
   };
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_ir_finder_test.html b/trace-viewer/trace_viewer/extras/rail/rail_ir_finder_test.html
index 596a51e..7357650 100644
--- a/trace-viewer/trace_viewer/extras/rail/rail_ir_finder_test.html
+++ b/trace-viewer/trace_viewer/extras/rail/rail_ir_finder_test.html
@@ -9,18 +9,18 @@
 <link rel="import" href="/extras/chrome/chrome_test_utils.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var audits = tv.e.audits;
+tr.b.unittest.testSuite(function() {
+  var audits = tr.e.audits;
 
   function newRIRF(customizeModelCallback) {
-    var model = tv.e.audits.newChromeModel(customizeModelCallback);
-    var modelHelper = new tv.e.audits.ChromeModelHelper(model);
-    return new tv.e.audits.RAILIRFinder(model, modelHelper);
+    var model = tr.e.audits.newChromeModel(customizeModelCallback);
+    var modelHelper = new tr.e.audits.ChromeModelHelper(model);
+    return new tr.e.rail.RAILIRFinder(model, modelHelper);
   }
 
   test('twoScrollsNoFling', function() {
@@ -91,33 +91,18 @@
     assert.equal(1, rirf.getAllFrameEvents().length);
   });
 
-  test('LoadingEvent', function() {
-    var rirf = newRIRF(function(model) {
-      audits.addGeneralLatencyInfoEvent(model, {start: 0, end: 100});
-      audits.addLoadingEvent(model, {start: 1, end: 10});
-    });
-    assert.equal(1, rirf.getAllLoadAndNetEvents().length);
-  });
-
-  test('NetworkEvent', function() {
-    var rirf = newRIRF(function(model) {
-      audits.addGeneralLatencyInfoEvent(model, {start: 0, end: 100});
-      audits.addNetworkEvent(model, {start: 1, end: 10});
-    });
-    assert.equal(1, rirf.getAllLoadAndNetEvents().length);
-  });
-
-  test('CommitToFirstFrame', function() {
+  test('Load', function() {
     var rirf = newRIRF(function(model) {
       audits.addProvisionalLoadEvent(model, {start: 1, end: 10});
       audits.addFrameEvent(model, {start: 11, end: 20});
     });
-    var loads = rirf.modelHelper.browser.getCommitProvisionalLoadEventsInRange(
-      rirf.model.bounds);
+    var loads = rirf.modelHelper.browserHelper.
+      getCommitProvisionalLoadEventsInRange(
+        rirf.model.bounds);
     assert.equal(1, loads.length);
     var irs = rirf.findAllInteractionRecords();
-    assert.equal(2, irs.length);
-    assert.equal('CommitToFirstFrame', irs[0].title);
+    assert.equal(1, irs.length);
+    assert.equal('Load', irs[0].title);
     assert.equal(1, irs[0].start);
     assert.equal(20, irs[0].end);
   });
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_score.html b/trace-viewer/trace_viewer/extras/rail/rail_score.html
index 59c6bae..2808bec 100644
--- a/trace-viewer/trace_viewer/extras/rail/rail_score.html
+++ b/trace-viewer/trace_viewer/extras/rail/rail_score.html
@@ -5,45 +5,48 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/base/base.html">
-<link rel="import" href="/base/statistics.html">
-<link rel="import" href="/base/iteration_helpers.html">
+<link rel="import" href="/extras/rail/rail_interaction_record.html">
+
 <script>
 'use strict';
 
-tv.exportTo('tv.e.audits', function() {
-
-  function RAILScore() {
+tr.exportTo('tr.e.rail', function() {
+  function RAILScore(opt_irs) {
+    this.interactionRecords_ = [];
+    if (opt_irs)
+      this.interactionRecords_.push.apply(this.interactionRecords_, opt_irs);
   };
 
-  RAILScore.compute = function(rirs) {
+  RAILScore.prototype = {
+    get interactionRecords() {
+      return this.interactionRecords_;
+    },
+
+    get overallScore() {
+      if (!this.interactionRecords.length)
+        return undefined;
+      var overall = 0;
+      this.interactionRecords.forEach(function(ir) {
+        overall += Math.pow(ir.railScore, 2) / this.interactionRecords.length;
+        // TODO(benjhayden) Implement a better algorithm as discussed in the
+        // following document.
+        // https://docs.google.com/document/d/1d6cywyfR58uYBGJvq5eBebwKcVVvaaHxU1dJEj3LX3E
+      }.bind(this));
+      return overall;
+    }
+  };
+
+  RAILScore.fromModel = function(model) {
+    var rirs = model.interaction_records.filter(function(ir) {
+      return ir instanceof tr.e.rail.RAILInteractionRecord;
+    });
     if (rirs.length === 0)
-      throw new Error('Impossible');
-
-    var railScoresByTypeName = {};
-    rirs.forEach(function(ir) {
-      if (railScoresByTypeName[ir.railTypeName] === undefined)
-        railScoresByTypeName[ir.railTypeName] = [];
-      railScoresByTypeName[ir.railTypeName].push(ir);
-    });
-
-    var result = {};
-
-    var overallRailScores = [];
-    tv.b.iterItems(railScoresByTypeName, function(railTypeName, irs) {
-      var minRailScoreForType = tv.b.Statistics.sum(irs, function(ir) {
-        return ir.railScore;
-      });
-      result['sum(' + railTypeName + ')'] = minRailScoreForType;
-      overallRailScores.push(minRailScoreForType);
-    });
-
-    result.score = tv.b.Statistics.sum(overallRailScores);
-    return result;
-  }
+      return undefined;
+    return new RAILScore(rirs);
+  };
 
   return {
     RAILScore: RAILScore
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_score_side_panel.html b/trace-viewer/trace_viewer/extras/rail/rail_score_side_panel.html
new file mode 100644
index 0000000..a97c360
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/rail_score_side_panel.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 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="import" href="/extras/rail/rail_score.html">
+<link rel="import" href="/extras/rail/rail_score_span.html">
+<link rel="import" href="/base/ui/table.html">
+<link rel="import" href="/core/side_panel/side_panel.html">
+
+<polymer-element name='tr-e-rail-rail-score-side-panel'
+    extends='tr-c-side-panel'>
+  <template>
+    <style>
+    :host {
+      display: flex;
+      width: 250px;
+    }
+    #content {
+      flex-direction: column;
+      display: flex;
+    }
+    </style>
+
+    <tr-e-rail-rail-score-span id='score'></tr-e-rail-rail-score-span>
+    <tr-ui-table id="table"></tr-ui-table>
+  </template>
+
+  <script>
+  'use strict';
+
+  Polymer({
+    ready: function() {
+      this.rangeOfInterest_ = new tr.b.Range();
+      this.model_ = undefined;
+      this.railScore_ = undefined;
+    },
+
+    get textLabel() {
+      return 'RAIL Info';
+    },
+
+    supportsModel: function(m) {
+      if (m === undefined) {
+        return {
+          supported: false,
+          reason: 'Unknown tracing model'
+        };
+      }
+
+      var railScore = tr.e.rail.RAILScore.fromModel(m);
+      if (railScore === undefined) {
+        return {
+          supported: false,
+          reason: 'RAIL interactions were not found on the model'
+        };
+      }
+
+      return {
+        supported: true
+      };
+    },
+
+    get model() {
+      return this.model_;
+    },
+
+    set model(model) {
+      this.model_ = model;
+      this.railScore_ = tr.e.rail.RAILScore.fromModel(model);
+      this.$.score.railScore = this.railScore_;
+      this.updateTable_();
+    },
+
+    get listeningToKeys() {
+      return false;
+    },
+
+    set selection(selection) {
+    },
+
+    set rangeOfInterest(rangeOfInterest) {
+    },
+
+    updateTable_: function() {
+    }
+  });
+  </script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_score_side_panel_test.html b/trace-viewer/trace_viewer/extras/rail/rail_score_side_panel_test.html
new file mode 100644
index 0000000..6890eb1
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/rail_score_side_panel_test.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/extras/rail/rail_score_side_panel.html">
+<link rel="import" href="/core/test_utils.html">
+<link rel="import" href="/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  var test_utils = tr.c.test_utils;
+
+
+  function StubRAILInteractionRecord(args) {
+    var sd = test_utils.getStartAndDurationFromDict(args);
+    tr.e.rail.RAILInteractionRecord.call(
+         this, args.railTypeName, args.railTypeName,
+         sd.start, sd.duration);
+
+    this.args = args;
+  }
+
+  StubRAILInteractionRecord.prototype = {
+    __proto__: tr.e.rail.RAILInteractionRecord.prototype,
+
+    get normalizedUserPain() {
+      return this.args.normalizedUserPain;
+    },
+
+    get normalizedEfficiency() {
+      return this.args.normalizedEfficiency;
+    }
+  };
+
+  test('instantiate', function() {
+    var panel = document.createElement('tr-e-rail-rail-score-side-panel');
+    panel.model = test_utils.newModel(function(model) {
+      model.addInteractionRecord(new StubRAILInteractionRecord({
+        start: 0, end: 100,
+        railTypeName: 'rail_idle',
+        normalizedEfficiency: 0.8,
+        normalizedUserPain: 0.0
+      }));
+      model.addInteractionRecord(new StubRAILInteractionRecord({
+        start: 100, end: 200,
+        railTypeName: 'rail_response',
+        normalizedEfficiency: 1.,
+        normalizedUserPain: 0.0
+      }));
+    });
+    panel.style.height = '200px';
+
+    this.addHTMLOutput(panel);
+  });
+});
+</script>
\ No newline at end of file
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_score_span.html b/trace-viewer/trace_viewer/extras/rail/rail_score_span.html
new file mode 100644
index 0000000..e4d3d45
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/rail_score_span.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/extras/rail/rail_score.html">
+<polymer-element name="tr-e-rail-rail-score-span">
+  <template>
+  <style>
+    :host {
+      display: span;
+    }
+  </style>
+  <span id="content">
+    <span>RAIL Score: </span><span id="score"></span>
+  </span>
+  </template>
+  <script>
+  'use strict';
+
+  Polymer({
+    created: function() {
+      this.railScore_ = undefined;
+    },
+
+    ready: function() {
+      this.updateContent_();
+    },
+
+    get railScore() {
+      return this.railScore_;
+    },
+
+    set railScore(railScore) {
+      this.railScore_ = railScore;
+      this.updateContent_();
+    },
+
+    updateContent_: function() {
+      if (this.railScore_ === undefined) {
+        this.$.content.style.display = 'none';
+        return;
+      }
+      this.$.content.style.display = '';
+      var overallScore = this.railScore_.overallScore;
+      this.$.score.textContent = overallScore.toLocaleString(
+          undefined,
+          {minimumFractionDigits: 3});
+    }
+  });
+  </script>
+</polymer-element>
diff --git a/trace-viewer/trace_viewer/extras/rail/rail_score_test.html b/trace-viewer/trace_viewer/extras/rail/rail_score_test.html
new file mode 100644
index 0000000..a3ba978
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/rail_score_test.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/extras/rail/rail_score.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('zeroInteractionRecords', function() {
+    var score = new tr.e.rail.RAILScore();
+    assert.equal(0, score.interactionRecords.length);
+    assert.isUndefined(score.overallScore);
+  });
+
+  test('overallScore', function() {
+    var score = new tr.e.rail.RAILScore([
+      {railScore: 0.9},
+      {railScore: 1.0},
+      {railScore: 0.89},
+      {railScore: 1.0},
+      {railScore: 0.1}
+    ]);
+    assert.equal(5, score.interactionRecords.length);
+
+    var expectedOverallScore = 0.72;
+    assert.closeTo(score.overallScore, 0.72, 0.01);
+  });
+
+  test('fromModel', function() {
+    var model = tr.e.audits.newChromeModel(function(model) {
+      model.addInteractionRecord(new tr.e.rail.RAILInteractionRecord(
+          'Idle', 'rail_idle', 0, 1));
+    });
+    var score = tr.e.rail.RAILScore.fromModel(model);
+    assert.equal(1, score.interactionRecords.length);
+  });
+
+  test('fromEmptyModel', function() {
+    var model = tr.e.audits.newChromeModel(function(model) {
+    });
+    assert.isUndefined(tr.e.rail.RAILScore.fromModel(model));
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/extras/rail/response_interaction_record.html b/trace-viewer/trace_viewer/extras/rail/response_interaction_record.html
new file mode 100644
index 0000000..d07a389
--- /dev/null
+++ b/trace-viewer/trace_viewer/extras/rail/response_interaction_record.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/extras/rail/rail_interaction_record.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview The Response phase of RAIL.
+ */
+tr.exportTo('tr.e.rail', function() {
+  function ResponseInteractionRecord(start, duration) {
+    tr.e.rail.RAILInteractionRecord.call(
+        this, 'Response', 'rail_response',
+        start, duration);
+  }
+
+  ResponseInteractionRecord.prototype = {
+    __proto__: tr.e.rail.RAILInteractionRecord.prototype,
+
+    get normalizedUserPain() {
+      return 0;
+    },
+
+    get normalizedEfficiency() {
+      return 1;
+    }
+  };
+
+  return {
+    ResponseInteractionRecord: ResponseInteractionRecord
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel.html b/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel.html
index d18eda0..59eb2e1 100644
--- a/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel.html
+++ b/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel.html
@@ -6,15 +6,15 @@
 -->
 
 <link rel="import" href="/extras/chrome/chrome_model_helper.html">
-<link rel="import" href="/core/analysis/table_builder.html">
+<link rel="import" href="/base/ui/table.html">
 <link rel="import" href="/core/side_panel/side_panel.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/base/statistics.html">
 <link rel="import" href="/base/ui/dom_helpers.html">
 <link rel="import" href="/base/ui/line_chart.html">
 
-<polymer-element name='tv-e-analysis-side-panel-alerts'
-    extends='tv-c-side-panel'>
+<polymer-element name='tr-e-s-alerts-side-panel'
+    extends='tr-c-side-panel'>
   <template>
     <style>
     :host {
@@ -38,7 +38,7 @@
 
   Polymer({
     ready: function() {
-      this.rangeOfInterest_ = new tv.b.Range();
+      this.rangeOfInterest_ = new tr.b.Range();
       this.selection_ = undefined;
     },
 
@@ -70,8 +70,8 @@
         return alert.title === alertTypeString;
       });
 
-      var event = new tv.c.RequestSelectionChangeEvent();
-      event.selection = new tv.c.Selection(alertsOfType);
+      var event = new tr.c.RequestSelectionChangeEvent();
+      event.selection = new tr.c.Selection(alertsOfType);
       this.dispatchEvent(event);
     },
 
@@ -118,7 +118,7 @@
     createAlertsTable_: function(alerts) {
       var alertsByType = this.alertsByType_(alerts);
 
-      var table = document.createElement('tracing-analysis-nested-table');
+      var table = document.createElement('tr-b-ui-table');
       table.tableColumns = this.alertsTableColumns_();
       table.tableRows = this.alertsTableRows_(alertsByType);
       table.supportsSelection = true;
@@ -158,7 +158,9 @@
       };
     },
 
-    textLabel: 'Alerts'
+    get textLabel() {
+      return 'Alerts';
+    }
   });
   </script>
 </polymer-element>
diff --git a/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel_test.html b/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel_test.html
index 942e7c2..2264495 100644
--- a/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel_test.html
+++ b/trace-viewer/trace_viewer/extras/side_panel/alerts_side_panel_test.html
@@ -7,22 +7,22 @@
 
 <link rel="import" href="/extras/side_panel/alerts_side_panel.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ALERT_INFO_1 = new tv.c.trace_model.EventInfo(
+tr.b.unittest.testSuite(function() {
+  var ALERT_INFO_1 = new tr.model.EventInfo(
     'Alert 1', 'Critical alert');
-  var ALERT_INFO_2 = new tv.c.trace_model.EventInfo(
+  var ALERT_INFO_2 = new tr.model.EventInfo(
     'Alert 2', 'Warning alert');
 
   test('instantiate', function() {
-    var panel = document.createElement('tv-e-analysis-side-panel-alerts');
+    var panel = document.createElement('tr-e-s-alerts-side-panel');
     panel.model = createModelWithAlerts([
-      new tv.c.trace_model.Alert(ALERT_INFO_1, 5),
-      new tv.c.trace_model.Alert(ALERT_INFO_2, 35)
+      new tr.model.Alert(ALERT_INFO_1, 5),
+      new tr.model.Alert(ALERT_INFO_2, 35)
     ]);
     panel.style.height = '100px';
 
@@ -30,11 +30,11 @@
   });
 
   test('selectAlertsOfType', function() {
-    var panel = document.createElement('tv-e-analysis-side-panel-alerts');
+    var panel = document.createElement('tr-e-s-alerts-side-panel');
     var alerts = [
-      new tv.c.trace_model.Alert(ALERT_INFO_1, 1),
-      new tv.c.trace_model.Alert(ALERT_INFO_1, 2),
-      new tv.c.trace_model.Alert(ALERT_INFO_2, 3)
+      new tr.model.Alert(ALERT_INFO_1, 1),
+      new tr.model.Alert(ALERT_INFO_1, 2),
+      new tr.model.Alert(ALERT_INFO_2, 3)
     ];
     panel.model = createModelWithAlerts(alerts);
     panel.style.height = '100px';
@@ -53,7 +53,7 @@
   });
 
   function createModelWithAlerts(alerts) {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.alerts = alerts;
     return m;
   };
diff --git a/trace-viewer/trace_viewer/extras/side_panel/input_latency.html b/trace-viewer/trace_viewer/extras/side_panel/input_latency_side_panel.html
similarity index 78%
rename from trace-viewer/trace_viewer/extras/side_panel/input_latency.html
rename to trace-viewer/trace_viewer/extras/side_panel/input_latency_side_panel.html
index da5696f..8e63e4e 100644
--- a/trace-viewer/trace_viewer/extras/side_panel/input_latency.html
+++ b/trace-viewer/trace_viewer/extras/side_panel/input_latency_side_panel.html
@@ -12,7 +12,8 @@
 <link rel="import" href="/base/ui/dom_helpers.html">
 <link rel="import" href="/base/ui/line_chart.html">
 
-<polymer-element name='tv-e-side-panel-input-latency' extends='tv-c-side-panel'>
+<polymer-element name='tr-e-s-input-latency-side-panel'
+    extends='tr-c-side-panel'>
   <template>
     <style>
     :host {
@@ -41,8 +42,8 @@
 
   Polymer({
     ready: function() {
-      this.rangeOfInterest_ = new tv.b.Range();
-      this.frametimeType_ = tv.e.audits.IMPL_FRAMETIME_TYPE;
+      this.rangeOfInterest_ = new tr.b.Range();
+      this.frametimeType_ = tr.e.audits.IMPL_FRAMETIME_TYPE;
       this.latencyChart_ = undefined;
       this.frametimeChart_ = undefined;
       this.selectedProcessId_ = undefined;
@@ -57,7 +58,7 @@
     set model(model) {
       this.model_ = model;
       if (this.model_)
-        this.modelHelper_ = new tv.e.audits.ChromeModelHelper(model);
+        this.modelHelper_ = new tr.e.audits.ChromeModelHelper(model);
       else
         this.modelHelper_ = undefined;
 
@@ -104,7 +105,7 @@
       if (this.latencyChart_ === undefined)
         return;
 
-      var r = new tv.b.Range();
+      var r = new tr.b.Range();
       if (this.mouseDownIndex_ === undefined) {
         this.latencyChart_.brushedRange = r;
         return;
@@ -122,10 +123,10 @@
             latencySlices.push(event);
         });
       });
-      latencySlices = tv.e.audits.getSlicesIntersectingRange(r, latencySlices);
+      latencySlices = tr.e.audits.getSlicesIntersectingRange(r, latencySlices);
 
-      var event = new tv.c.RequestSelectionChangeEvent();
-      event.selection = new tv.c.Selection(latencySlices);
+      var event = new tr.c.RequestSelectionChangeEvent();
+      event.selection = new tr.c.Selection(latencySlices);
       this.latencyChart_.dispatchEvent(event);
     },
 
@@ -150,7 +151,6 @@
     },
 
     updateToolbar_: function() {
-      var rendererProcesses = this.modelHelper_.rendererProcesses;
       var browserProcess = this.modelHelper_.browserProcess;
       var labels = [];
 
@@ -159,25 +159,28 @@
         labels.push({label: label_str, value: browserProcess.pid});
       }
 
-      rendererProcesses.forEach(function(rendererProcess) {
-        var label_str = 'Renderer: ' + rendererProcess.pid;
-        labels.push({label: label_str, value: rendererProcess.pid});
-      });
+      tr.b.iterItems(this.modelHelper_.rendererHelpers,
+        function(pid, rendererHelper) {
+          var rendererProcess = rendererHelper.process;
+          var label_str = 'Renderer: ' + rendererProcess.userFriendlyName;
+          labels.push({label: label_str, value: rendererProcess.userFriendlyName
+        });
+      }, this);
 
       if (labels.length === 0)
         return;
 
       this.selectedProcessId_ = labels[0].value;
       var toolbarEl = this.$.toolbar;
-      toolbarEl.appendChild(tv.b.ui.createSelector(
+      toolbarEl.appendChild(tr.b.ui.createSelector(
           this, 'frametimeType',
           'inputLatencySidePanel.frametimeType', this.frametimeType_,
           [{label: 'Main Thread Frame Times',
-            value: tv.e.audits.MAIN_FRAMETIME_TYPE},
+            value: tr.e.audits.MAIN_FRAMETIME_TYPE},
            {label: 'Impl Thread Frame Times',
-            value: tv.e.audits.IMPL_FRAMETIME_TYPE}
+            value: tr.e.audits.IMPL_FRAMETIME_TYPE}
           ]));
-      toolbarEl.appendChild(tv.b.ui.createSelector(
+      toolbarEl.appendChild(tr.b.ui.createSelector(
           this, 'selectedProcessId',
           'inputLatencySidePanel.selectedProcessId',
           this.selectedProcessId_,
@@ -192,7 +195,7 @@
     },
 
     createLatencyLineChart: function(data, title) {
-      var chart = new tv.b.ui.LineChart();
+      var chart = new tr.b.ui.LineChart();
       var width = 600;
       if (document.body.clientWidth != undefined)
         width = document.body.clientWidth * 0.5;
@@ -214,20 +217,23 @@
       var rangeOfInterest = this.currentRangeOfInterest;
 
       var chromeProcess;
-      if (this.modelHelper_.renderers[this.selectedProcessId_])
-        chromeProcess = this.modelHelper_.renderers[this.selectedProcessId_];
+      if (this.modelHelper_.rendererHelpers[this.selectedProcessId_])
+        chromeProcess = this.modelHelper_.rendererHelpers[
+          this.selectedProcessId_
+        ];
       else
-        chromeProcess = this.modelHelper_.browser;
+        chromeProcess = this.modelHelper_.browserHelper;
 
       var frameEvents = chromeProcess.getFrameEventsInRange(
           this.frametimeType, rangeOfInterest);
 
-      var frametimeData = tv.e.audits.getFrametimeDataFromEvents(frameEvents);
-      var averageFrametime = tv.b.Statistics.mean(frametimeData, function(d) {
+      var frametimeData = tr.e.audits.getFrametimeDataFromEvents(frameEvents);
+      var averageFrametime = tr.b.Statistics.mean(frametimeData, function(d) {
         return d.frametime;
       });
 
-      var latencyEvents = this.modelHelper_.browser.getLatencyEventsInRange(
+      var latencyEvents = this.modelHelper_.browserHelper.
+        getLatencyEventsInRange(
           rangeOfInterest);
 
       var latencyData = [];
@@ -240,19 +246,19 @@
         });
       });
 
-      var averageLatency = tv.b.Statistics.mean(latencyData, function(d) {
+      var averageLatency = tr.b.Statistics.mean(latencyData, function(d) {
         return d.latency;
       });
 
       // Create summary.
       var latencySummaryText = document.createElement('div');
-      latencySummaryText.appendChild(tv.b.ui.createSpan({
+      latencySummaryText.appendChild(tr.b.ui.createSpan({
         textContent: 'Average Latency ' + averageLatency + ' ms',
         bold: true}));
       resultArea.appendChild(latencySummaryText);
 
       var frametimeSummaryText = document.createElement('div');
-      frametimeSummaryText.appendChild(tv.b.ui.createSpan({
+      frametimeSummaryText.appendChild(tr.b.ui.createSpan({
         textContent: 'Average Frame Time ' + averageFrametime + ' ms',
         bold: true}));
       resultArea.appendChild(frametimeSummaryText);
@@ -289,18 +295,19 @@
         };
       }
 
-      if (!tv.e.audits.ChromeModelHelper.supportsModel(m)) {
+      if (!tr.e.audits.ChromeModelHelper.supportsModel(m)) {
         return {
           supported: false,
           reason: 'No Chrome browser or renderer process found'
         };
       }
 
-      var modelHelper = new tv.e.audits.ChromeModelHelper(m);
-      if (modelHelper.browser && modelHelper.browser.hasLatencyEvents) {
-        return {
-          supported: true
-        };
+      var modelHelper = new tr.e.audits.ChromeModelHelper(m);
+      if (modelHelper.browserHelper &&
+        modelHelper.browserHelper.hasLatencyEvents) {
+          return {
+            supported: true
+          };
       }
 
       return {
@@ -310,7 +317,9 @@
       };
     },
 
-    textLabel: 'Input Latency'
+    get textLabel() {
+      return 'Input Latency';
+    }
   });
   </script>
 </polymer-element>
diff --git a/trace-viewer/trace_viewer/extras/side_panel/input_latency_test.html b/trace-viewer/trace_viewer/extras/side_panel/input_latency_side_panel_test.html
similarity index 87%
rename from trace-viewer/trace_viewer/extras/side_panel/input_latency_test.html
rename to trace-viewer/trace_viewer/extras/side_panel/input_latency_side_panel_test.html
index 4c98725..d219010 100644
--- a/trace-viewer/trace_viewer/extras/side_panel/input_latency_test.html
+++ b/trace-viewer/trace_viewer/extras/side_panel/input_latency_side_panel_test.html
@@ -5,15 +5,15 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/extras/side_panel/input_latency.html">
+<link rel="import" href="/extras/side_panel/input_latency_side_panel.html">
 <link rel="import" href="/extras/importer/trace_event_importer.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('basic', function() {
     var latencyData = [
       {
@@ -33,7 +33,7 @@
         latency: 23
       }
     ];
-    var lc = document.createElement('tv-e-side-panel-input-latency');
+    var lc = document.createElement('tr-e-s-input-latency-side-panel');
     var latencyChart = lc.createLatencyLineChart(latencyData, 'latency');
     this.addHTMLOutput(latencyChart);
 
@@ -55,7 +55,7 @@
         frametime: 23
       }
     ];
-    var lc = document.createElement('tv-e-side-panel-input-latency');
+    var lc = document.createElement('tr-e-s-input-latency-side-panel');
     var frametimeChart = lc.createLatencyLineChart(frametimeData, 'frametime');
     this.addHTMLOutput(frametimeChart);
   });
@@ -115,11 +115,11 @@
       'name': 'thread_name',
       'args': {'name': 'CrBrowserMain'}});
 
-    var panel = document.createElement('tv-e-side-panel-input-latency');
+    var panel = document.createElement('tr-e-s-input-latency-side-panel');
     this.addHTMLOutput(panel);
 
     var selectionChanged = false;
-    panel.model = new tv.c.TraceModel(events);
+    panel.model = new tr.Model(events);
     function listener(e) {
       selectionChanged = true;
       assert.equal(e.selection.length, 3);
diff --git a/trace-viewer/trace_viewer/extras/side_panel/time_summary.html b/trace-viewer/trace_viewer/extras/side_panel/time_summary_side_panel.html
similarity index 90%
rename from trace-viewer/trace_viewer/extras/side_panel/time_summary.html
rename to trace-viewer/trace_viewer/extras/side_panel/time_summary_side_panel.html
index e98486c..6fecbeb 100644
--- a/trace-viewer/trace_viewer/extras/side_panel/time_summary.html
+++ b/trace-viewer/trace_viewer/extras/side_panel/time_summary_side_panel.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/core/selection.html">
 <link rel="import" href="/core/side_panel/side_panel.html">
 <link rel="import" href="/base/iteration_helpers.html">
@@ -13,7 +13,8 @@
 <link rel="import" href="/base/ui/dom_helpers.html">
 <link rel="import" href="/base/ui/pie_chart.html">
 
-<polymer-element name="tv-e-side-panel-time-summary" extends="tv-c-side-panel">
+<polymer-element name="tr-e-s-time-summary-side-panel"
+    extends="tr-c-side-panel">
   <template>
     <style>
     :host {
@@ -58,7 +59,7 @@
 
     ResultsForGroup.prototype = {
       get wallTime() {
-        var wallSum = tv.b.Statistics.sum(
+        var wallSum = tr.b.Statistics.sum(
             this.topLevelSlices, function(x) { return x.duration; });
         return wallSum;
       },
@@ -119,7 +120,7 @@
 
     Polymer({
       ready: function() {
-        this.rangeOfInterest_ = new tv.b.Range();
+        this.rangeOfInterest_ = new tr.b.Range();
         this.selection_ = undefined;
         this.groupBy_ = GROUP_BY_PROCESS_NAME;
         this.groupingUnit_ = CPU_TIME_GROUPING_UNIT;
@@ -127,7 +128,7 @@
         this.chart_ = undefined;
 
         var toolbarEl = this.$.toolbar;
-        this.groupBySelector_ = tv.b.ui.createSelector(
+        this.groupBySelector_ = tr.b.ui.createSelector(
             this, 'groupBy',
             'timeSummarySidePanel.groupBy', this.groupBy_,
             [{label: 'Group by process', value: GROUP_BY_PROCESS_NAME},
@@ -135,7 +136,7 @@
             ]);
         toolbarEl.appendChild(this.groupBySelector_);
 
-        this.groupingUnitSelector_ = tv.b.ui.createSelector(
+        this.groupingUnitSelector_ = tr.b.ui.createSelector(
             this, 'groupingUnit',
             'timeSummarySidePanel.groupingUnit', this.groupingUnit_,
             [{label: 'Wall time', value: WALL_TIME_GROUPING_UNIT},
@@ -143,7 +144,7 @@
             ]);
         toolbarEl.appendChild(this.groupingUnitSelector_);
 
-        this.showCpuIdleTimeCheckbox_ = tv.b.ui.createCheckBox(
+        this.showCpuIdleTimeCheckbox_ = tr.b.ui.createCheckBox(
             this, 'showCpuIdleTime',
             'timeSummarySidePanel.showCpuIdleTime', this.showCpuIdleTime_,
             'Show CPU idle time');
@@ -164,7 +165,7 @@
         });
 
         // Figure out total array range.
-        var sum = tv.b.Statistics.sum(groups, getValue);
+        var sum = tr.b.Statistics.sum(groups, getValue);
         if (opt_extraValue !== undefined)
           sum += opt_extraValue;
 
@@ -205,13 +206,13 @@
 
       createPieChartFromResultGroups: function(
           groups, title, getValue, opt_extraData) {
-        var chart = new tv.b.ui.PieChart();
+        var chart = new tr.b.ui.PieChart();
 
         function pushDataForGroup(data, resultsForGroup, value) {
           data.push({
             label: resultsForGroup.name,
             value: value,
-            valueText: tv.c.analysis.tsString(value),
+            valueText: tr.b.units.tsString(value),
             resultsForGroup: resultsForGroup
           });
         }
@@ -220,8 +221,8 @@
           if (resultsForGroup === undefined)
             return;
 
-          var event = new tv.c.RequestSelectionChangeEvent();
-          event.selection = new tv.c.Selection(resultsForGroup.allSlices);
+          var event = new tr.c.RequestSelectionChangeEvent();
+          event.selection = new tr.c.Selection(resultsForGroup.allSlices);
           event.selection.timeSummaryGroupName = resultsForGroup.name;
           chart.dispatchEvent(event);
         });
@@ -345,11 +346,11 @@
 
         // Create summary.
         var summaryText = document.createElement('div');
-        summaryText.appendChild(tv.b.ui.createSpan({
+        summaryText.appendChild(tr.b.ui.createSpan({
           textContent: 'Total ' + this.groupingUnit_ + ': ',
           bold: true}));
-        summaryText.appendChild(tv.b.ui.createSpan({
-          textContent: tv.c.analysis.tsString(getValueFromGroup(allGroup))}));
+        summaryText.appendChild(tr.b.ui.createSpan({
+          textContent: tr.b.units.tsString(getValueFromGroup(allGroup))}));
         resultArea.appendChild(summaryText);
 
         // If needed, add in the idle time.
@@ -364,7 +365,7 @@
           extraData.push({
             label: 'CPU Idle',
             value: idleTime,
-            valueText: tv.c.analysis.tsString(idleTime)
+            valueText: tr.b.units.tsString(idleTime)
           });
           extraValue += idleTime;
         }
@@ -372,13 +373,13 @@
         // Create the actual chart.
         var otherGroup = this.generateResultsForGroup(this.model_, 'Other');
         var groups = this.trimPieChartData(
-            tv.b.dictionaryValues(resultsByGroupName),
+            tr.b.dictionaryValues(resultsByGroupName),
             otherGroup,
             getValueFromGroup,
             extraValue);
 
         if (groups.length == 0) {
-          resultArea.appendChild(tv.b.ui.createSpan({textContent: 'No data'}));
+          resultArea.appendChild(tr.b.ui.createSpan({textContent: 'No data'}));
           return undefined;
         }
 
@@ -389,8 +390,8 @@
         resultArea.appendChild(this.chart_);
 
         this.chart_.addEventListener('click', function() {
-          var event = new tv.c.RequestSelectionChangeEvent();
-          event.selection = new tv.c.Selection([]);
+          var event = new tr.c.RequestSelectionChangeEvent();
+          event.selection = new tr.c.Selection([]);
           this.dispatchEvent(event);
         });
         this.chart_.setSize(this.chart_.getMinSize());
@@ -427,7 +428,9 @@
         };
       },
 
-      textLabel: 'Time Summary'
+      get textLabel() {
+        return 'Time Summary';
+      }
     });
   }());
   </script>
diff --git a/trace-viewer/trace_viewer/extras/side_panel/time_summary_test.html b/trace-viewer/trace_viewer/extras/side_panel/time_summary_side_panel_test.html
similarity index 87%
rename from trace-viewer/trace_viewer/extras/side_panel/time_summary_test.html
rename to trace-viewer/trace_viewer/extras/side_panel/time_summary_side_panel_test.html
index 505305e..9e135c2 100644
--- a/trace-viewer/trace_viewer/extras/side_panel/time_summary_test.html
+++ b/trace-viewer/trace_viewer/extras/side_panel/time_summary_side_panel_test.html
@@ -5,19 +5,19 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/extras/side_panel/time_summary.html">
+<link rel="import" href="/extras/side_panel/time_summary_side_panel.html">
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
+tr.b.unittest.testSuite(function() {
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
 
   function createModel(opt_options) {
     var options = opt_options || {};
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([], false, false, function() {
       if (options.provideSoftwareMeasuredCpuCount)
         m.kernel.softwareMeasuredCpuCount = 2;
@@ -42,7 +42,7 @@
   }
 
   test('group', function() {
-    var ts = document.createElement('tv-e-side-panel-time-summary');
+    var ts = document.createElement('tr-e-s-time-summary-side-panel');
     var m = createModel();
     var group = ts.generateResultsForGroup(m, 'foo');
     group.appendThreadSlices(m.bounds, m.processes[1].threads[2]);
@@ -134,10 +134,10 @@
       }
     ];
 
-    var ts = document.createElement('tv-e-side-panel-time-summary');
+    var ts = document.createElement('tr-e-s-time-summary-side-panel');
 
     var groups = [];
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([], false, false, function() {
       var start = 0;
       groupData.forEach(function(groupData) {
@@ -158,7 +158,7 @@
     var newGroups = ts.trimPieChartData(groups, otherGroup, getValueFromGroup);
 
     // Visualize the data once its trimmed.
-    var ce = document.createElement('tv-e-side-panel-time-summary');
+    var ce = document.createElement('tr-e-s-time-summary-side-panel');
     var chart = ce.createPieChartFromResultGroups(
         newGroups, 'Trimmed', getValueFromGroup);
     this.addHTMLOutput(chart);
@@ -168,7 +168,7 @@
   test('basicInWallTimeMode', function() {
     var m = createModel();
 
-    var panel = document.createElement('tv-e-side-panel-time-summary');
+    var panel = document.createElement('tr-e-s-time-summary-side-panel');
     this.addHTMLOutput(panel);
     panel.model = m;
     panel.groupingUnit = 'Wall time';
@@ -178,7 +178,7 @@
   test('basicInCpuTimeModeButNoCpuData', function() {
     var m = createModel();
 
-    var panel = document.createElement('tv-e-side-panel-time-summary');
+    var panel = document.createElement('tr-e-s-time-summary-side-panel');
     this.addHTMLOutput(panel);
     panel.model = m;
     panel.groupingUnit = 'CPU time';
@@ -190,7 +190,7 @@
       provideSoftwareMeasuredCpuCount: true
     });
 
-    var panel = document.createElement('tv-e-side-panel-time-summary');
+    var panel = document.createElement('tr-e-s-time-summary-side-panel');
     this.addHTMLOutput(panel);
     panel.model = m;
     panel.groupingUnit = 'CPU time';
diff --git a/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track.html b/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track.html
index 67fc64a..ed6f586 100644
--- a/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track.html
+++ b/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track.html
@@ -15,11 +15,11 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.system_stats', function() {
-  var EventPresenter = tv.c.EventPresenter;
+tr.exportTo('tr.e.system_stats', function() {
+  var EventPresenter = tr.c.EventPresenter;
 
-  var palette = tv.b.ui.getColorPalette();
-  var highlightIdBoost = tv.b.ui.getColorPaletteHighlightIdBoost();
+  var palette = tr.b.ui.getColorPalette();
+  var highlightIdBoost = tr.b.ui.getColorPaletteHighlightIdBoost();
 
   var statCount;
 
@@ -49,15 +49,15 @@
    * @extends {StackedBarsTrack}
    */
 
-  var SystemStatsInstanceTrack = tv.b.ui.define(
-      'system-stats-instance-track', tv.c.tracks.StackedBarsTrack);
+  var SystemStatsInstanceTrack = tr.b.ui.define(
+      'system-stats-instance-track', tr.c.tracks.StackedBarsTrack);
 
   SystemStatsInstanceTrack.prototype = {
 
-    __proto__: tv.c.tracks.StackedBarsTrack.prototype,
+    __proto__: tr.c.tracks.StackedBarsTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.StackedBarsTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.StackedBarsTrack.prototype.decorate.call(this, viewport);
       this.classList.add('system-stats-instance-track');
       this.objectInstance_ = null;
     },
@@ -192,7 +192,7 @@
 
     draw: function(type, viewLWorld, viewRWorld) {
       switch (type) {
-        case tv.c.tracks.DrawType.GENERAL_EVENT:
+        case tr.c.tracks.DrawType.GENERAL_EVENT:
           this.drawStatBars_(viewLWorld, viewRWorld);
           break;
       }
@@ -213,7 +213,7 @@
       var maxStats = this.maxStats_;
 
       var objectSnapshots = this.objectInstance_.snapshots;
-      var lowIndex = tv.b.findLowIndexInSortedArray(
+      var lowIndex = tr.b.findLowIndexInSortedArray(
           objectSnapshots,
           function(snapshot) {
             return snapshot.ts;
@@ -345,7 +345,7 @@
     }
   };
 
-  tv.c.tracks.ObjectInstanceTrack.register(
+  tr.c.tracks.ObjectInstanceTrack.register(
       SystemStatsInstanceTrack,
       {typeName: 'base::TraceEventSystemStatsMonitor::SystemStats'});
 
diff --git a/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track_test.html b/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track_test.html
index f8dd6ca..f6a4e88 100644
--- a/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track_test.html
+++ b/trace-viewer/trace_viewer/extras/system_stats/system_stats_instance_track_test.html
@@ -8,19 +8,19 @@
 <link rel="import" href="/extras/system_stats/system_stats.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/selection_state.html">
 <link rel="import" href="/core/timeline_viewport.html">
 <link rel="import" href="/core/tracks/drawing_container.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
-  var SystemStatsInstanceTrack = tv.e.system_stats.SystemStatsInstanceTrack;
-  var Viewport = tv.c.TimelineViewport;
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
+  var SystemStatsInstanceTrack = tr.e.system_stats.SystemStatsInstanceTrack;
+  var Viewport = tr.c.TimelineViewport;
 
   var createObjects = function() {
-    var objectInstance = new tv.c.trace_model.ObjectInstance({});
+    var objectInstance = new tr.model.ObjectInstance({});
     var snapshots = [];
 
     var stats1 = new Object();
@@ -34,9 +34,9 @@
     stats2['meminfo'] = new Object();
     stats2.meminfo['free'] = 20000;
 
-    snapshots.push(new tv.e.system_stats.SystemStatsSnapshot(objectInstance,
+    snapshots.push(new tr.e.system_stats.SystemStatsSnapshot(objectInstance,
                                                              10, stats1));
-    snapshots.push(new tv.e.system_stats.SystemStatsSnapshot(objectInstance,
+    snapshots.push(new tr.e.system_stats.SystemStatsSnapshot(objectInstance,
                                                              20, stats2));
 
     objectInstance.snapshots = snapshots;
@@ -50,7 +50,7 @@
 
     var div = document.createElement('div');
     var viewport = new Viewport(div);
-    var drawingContainer = new tv.c.tracks.DrawingContainer(viewport);
+    var drawingContainer = new tr.c.tracks.DrawingContainer(viewport);
     div.appendChild(drawingContainer);
 
     var track = new SystemStatsInstanceTrack(viewport);
@@ -61,7 +61,7 @@
     drawingContainer.invalidate();
 
     track.heading = 'testBasic';
-    var dt = new tv.c.TimelineDisplayTransform();
+    var dt = new tr.c.TimelineDisplayTransform();
     dt.xSetWorldBounds(0, 50, track.clientWidth);
     track.viewport.setDisplayTransformImmediately(dt);
   });
diff --git a/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot.html b/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot.html
index 6cd5161..f44074f 100644
--- a/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot.html
+++ b/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot.html
@@ -10,8 +10,8 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.system_stats', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.system_stats', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * @constructor
diff --git a/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot_view.html b/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot_view.html
index ce42b73..d77f3a2 100644
--- a/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot_view.html
+++ b/trace-viewer/trace_viewer/extras/system_stats/system_stats_snapshot_view.html
@@ -1,26 +1,26 @@
 <!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.
+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="/extras/system_stats/system_stats_snapshot_view.css">
 <link rel="import" href="/core/analysis/object_snapshot_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.system_stats', function() {
+tr.exportTo('tr.e.system_stats', function() {
   /*
    * Displays a system stats snapshot in a human readable form. @constructor
    */
-  var SystemStatsSnapshotView = tv.b.ui.define('system-stats-snapshot-view',
-      tv.c.analysis.ObjectSnapshotView);
+  var SystemStatsSnapshotView = tr.b.ui.define('system-stats-snapshot-view',
+      tr.c.analysis.ObjectSnapshotView);
 
   SystemStatsSnapshotView.prototype = {
-    __proto__: tv.c.analysis.ObjectSnapshotView.prototype,
+    __proto__: tr.c.analysis.ObjectSnapshotView.prototype,
 
     decorate: function() {
       this.classList.add('system-stats-snapshot-view');
@@ -71,7 +71,7 @@
     }
   };
 
-  tv.c.analysis.ObjectSnapshotView.register(
+  tr.c.analysis.ObjectSnapshotView.register(
       SystemStatsSnapshotView,
       {typeName: 'base::TraceEventSystemStatsMonitor::SystemStats'});
 
diff --git a/trace-viewer/trace_viewer/extras/systrace_config.html b/trace-viewer/trace_viewer/extras/systrace_config.html
index 0ce2a7f..3a023b3 100644
--- a/trace-viewer/trace_viewer/extras/systrace_config.html
+++ b/trace-viewer/trace_viewer/extras/systrace_config.html
@@ -10,4 +10,4 @@
 <link rel="import" href="/extras/importer/ddms_importer.html">
 <link rel="import" href="/extras/importer/linux_perf/ftrace_importer.html">
 <link rel="import" href="/extras/side_panel/alerts_side_panel.html">
-<link rel="import" href="/extras/audits/android_auditor.html">
+<link rel="import" href="/extras/android/android_auditor.html">
diff --git a/trace-viewer/trace_viewer/extras/tcmalloc/heap.html b/trace-viewer/trace_viewer/extras/tcmalloc/heap.html
index 9110914..8366a6c 100644
--- a/trace-viewer/trace_viewer/extras/tcmalloc/heap.html
+++ b/trace-viewer/trace_viewer/extras/tcmalloc/heap.html
@@ -4,13 +4,13 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 <link rel="import" href="/extras/chrome/cc/util.html">
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tcmalloc', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.e.tcmalloc', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * @constructor
@@ -23,7 +23,7 @@
     __proto__: ObjectSnapshot.prototype,
 
     preInitialize: function() {
-      tv.e.cc.preInitializeObject(this);
+      tr.e.cc.preInitializeObject(this);
 
       // TODO(jamescook): Any generic field setup can go here.
     },
diff --git a/trace-viewer/trace_viewer/extras/tcmalloc/heap_instance_track.html b/trace-viewer/trace_viewer/extras/tcmalloc/heap_instance_track.html
index 44b5032..108954b 100644
--- a/trace-viewer/trace_viewer/extras/tcmalloc/heap_instance_track.html
+++ b/trace-viewer/trace_viewer/extras/tcmalloc/heap_instance_track.html
@@ -15,8 +15,8 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tcmalloc', function() {
-  var EventPresenter = tv.c.EventPresenter;
+tr.exportTo('tr.e.tcmalloc', function() {
+  var EventPresenter = tr.c.EventPresenter;
 
   /**
    * A track that displays heap memory data.
@@ -24,15 +24,15 @@
    * @extends {StackedBarsTrack}
    */
 
-  var HeapInstanceTrack = tv.b.ui.define(
-      'heap-instance-track', tv.c.tracks.StackedBarsTrack);
+  var HeapInstanceTrack = tr.b.ui.define(
+      'heap-instance-track', tr.c.tracks.StackedBarsTrack);
 
   HeapInstanceTrack.prototype = {
 
-    __proto__: tv.c.tracks.StackedBarsTrack.prototype,
+    __proto__: tr.c.tracks.StackedBarsTrack.prototype,
 
     decorate: function(viewport) {
-      tv.c.tracks.StackedBarsTrack.prototype.decorate.call(this, viewport);
+      tr.c.tracks.StackedBarsTrack.prototype.decorate.call(this, viewport);
       this.classList.add('heap-instance-track');
       this.objectInstance_ = null;
     },
@@ -76,7 +76,7 @@
 
     draw: function(type, viewLWorld, viewRWorld) {
       switch (type) {
-        case tv.c.tracks.DrawType.GENERAL_EVENT:
+        case tr.c.tracks.DrawType.GENERAL_EVENT:
           this.drawEvents_(viewLWorld, viewRWorld);
           break;
       }
@@ -97,7 +97,7 @@
       var maxBytes = this.maxBytes_;
 
       var objectSnapshots = this.objectInstance_.snapshots;
-      var lowIndex = tv.b.findLowIndexInSortedArray(
+      var lowIndex = tr.b.findLowIndexInSortedArray(
           objectSnapshots,
           function(snapshot) {
             return snapshot.ts;
@@ -165,7 +165,7 @@
     }
   };
 
-  tv.c.tracks.ObjectInstanceTrack.register(
+  tr.c.tracks.ObjectInstanceTrack.register(
       HeapInstanceTrack,
       {typeName: 'memory::Heap'});
 
diff --git a/trace-viewer/trace_viewer/extras/tcmalloc/heap_test.html b/trace-viewer/trace_viewer/extras/tcmalloc/heap_test.html
index 6b13bf1..ad96893 100644
--- a/trace-viewer/trace_viewer/extras/tcmalloc/heap_test.html
+++ b/trace-viewer/trace_viewer/extras/tcmalloc/heap_test.html
@@ -10,8 +10,8 @@
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var HeapSnapshot = tv.e.tcmalloc.HeapSnapshot;
+tr.b.unittest.testSuite(function() {
+  var HeapSnapshot = tr.e.tcmalloc.HeapSnapshot;
 
   // Tests total allocation count.
   test('totals', function() {
diff --git a/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_instance_view.html b/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_instance_view.html
index fb4b464..2e85b95 100644
--- a/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_instance_view.html
+++ b/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_instance_view.html
@@ -7,25 +7,25 @@
 
 <link rel="stylesheet" href="/extras/tcmalloc/tcmalloc_instance_view.css">
 <link rel="import" href="/core/analysis/object_instance_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tcmalloc', function() {
+tr.exportTo('tr.e.tcmalloc', function() {
   /**
    * Displays tcmalloc heap memory information over time. A tcmalloc instance
    * has multiple snapshots.
    * @constructor
    */
-  var TcmallocInstanceView = tv.b.ui.define(
-      'tcmalloc-instance-view', tv.c.analysis.ObjectInstanceView);
+  var TcmallocInstanceView = tr.b.ui.define(
+      'tcmalloc-instance-view', tr.c.analysis.ObjectInstanceView);
 
   TcmallocInstanceView.prototype = {
-    __proto__: tv.c.analysis.ObjectInstanceView.prototype,
+    __proto__: tr.c.analysis.ObjectInstanceView.prototype,
 
     decorate: function() {
-      tv.c.analysis.ObjectInstanceView.prototype.decorate.apply(this);
+      tr.c.analysis.ObjectInstanceView.prototype.decorate.apply(this);
       this.classList.add('tcmalloc-instance-view');
     },
 
@@ -77,8 +77,8 @@
       var row = document.createElement('tr');
       var td = document.createElement('td');
       if (snapshot) {
-        var snapshotLink = document.createElement('tv-c-analysis-link');
-        snapshotLink.selection = new tv.c.Selection(snapshot);
+        var snapshotLink = document.createElement('tr-c-a-analysis-link');
+        snapshotLink.selection = new tr.c.Selection(snapshot);
         td.appendChild(snapshotLink);
       }
       row.appendChild(td);
@@ -99,7 +99,7 @@
     }
   };
 
-  tv.c.analysis.ObjectInstanceView.register(
+  tr.c.analysis.ObjectInstanceView.register(
       TcmallocInstanceView,
       {typeName: 'memory::Heap'});
 
diff --git a/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.html b/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.html
index fc16da3..77cd1a4 100644
--- a/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.html
+++ b/trace-viewer/trace_viewer/extras/tcmalloc/tcmalloc_snapshot_view.html
@@ -7,22 +7,22 @@
 
 <link rel="stylesheet" href="/extras/tcmalloc/tcmalloc_snapshot_view.css">
 <link rel="import" href="/core/analysis/object_snapshot_view.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tcmalloc', function() {
+tr.exportTo('tr.e.tcmalloc', function() {
   /*
    * Displays a heap memory snapshot in a human readable form.
    * @constructor
    */
-  var TcmallocSnapshotView = tv.b.ui.define(
+  var TcmallocSnapshotView = tr.b.ui.define(
       'heap-snapshot-view',
-      tv.c.analysis.ObjectSnapshotView);
+      tr.c.analysis.ObjectSnapshotView);
 
   TcmallocSnapshotView.prototype = {
-    __proto__: tv.c.analysis.ObjectSnapshotView.prototype,
+    __proto__: tr.c.analysis.ObjectSnapshotView.prototype,
 
     decorate: function() {
       this.classList.add('tcmalloc-snapshot-view');
@@ -165,7 +165,7 @@
     }
   };
 
-  tv.c.analysis.ObjectSnapshotView.register(
+  tr.c.analysis.ObjectSnapshotView.register(
       TcmallocSnapshotView,
       {typeName: 'memory::Heap'});
 
diff --git a/trace-viewer/trace_viewer/extras/tquery/context.html b/trace-viewer/trace_viewer/extras/tquery/context.html
index 87aa12c..ad1fa6a 100644
--- a/trace-viewer/trace_viewer/extras/tquery/context.html
+++ b/trace-viewer/trace_viewer/extras/tquery/context.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function Context() {
     this.event = undefined;
     this.ancestors = [];
diff --git a/trace-viewer/trace_viewer/extras/tquery/filter.html b/trace-viewer/trace_viewer/extras/tquery/filter.html
index 30d4b69..e300522 100644
--- a/trace-viewer/trace_viewer/extras/tquery/filter.html
+++ b/trace-viewer/trace_viewer/extras/tquery/filter.html
@@ -10,9 +10,9 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function Filter() {
-    tv.c.ScriptingObject.call(this);
+    tr.c.ScriptingObject.call(this);
   }
 
   Filter.normalizeFilterExpression = function(filterExpression) {
@@ -21,14 +21,14 @@
     if (filterExpression instanceof String ||
         typeof(filterExpression) == 'string' ||
         filterExpression instanceof RegExp) {
-      var filter = new tv.e.tquery.FilterHasTitle(filterExpression);
+      var filter = new tr.e.tquery.FilterHasTitle(filterExpression);
       return filter;
     }
     return filterExpression;
   };
 
   Filter.prototype = {
-    __proto__: tv.c.ScriptingObject.prototype,
+    __proto__: tr.c.ScriptingObject.prototype,
 
     evaluate: function(context) {
       throw new Error('Not implemented');
diff --git a/trace-viewer/trace_viewer/extras/tquery/filter_all_of.html b/trace-viewer/trace_viewer/extras/tquery/filter_all_of.html
index 31afd40..b47653d 100644
--- a/trace-viewer/trace_viewer/extras/tquery/filter_all_of.html
+++ b/trace-viewer/trace_viewer/extras/tquery/filter_all_of.html
@@ -11,20 +11,20 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function FilterAllOf(opt_subExpressions) {
-    tv.e.tquery.Filter.call(this);
+    tr.e.tquery.Filter.call(this);
     this.subExpressions = opt_subExpressions || [];
   }
 
   FilterAllOf.prototype = {
-    __proto__: tv.e.tquery.Filter.prototype,
+    __proto__: tr.e.tquery.Filter.prototype,
 
     set subExpressions(exprs) {
       this.subExpressions_ = [];
       for (var i = 0; i < exprs.length; i++) {
         this.subExpressions_.push(
-            tv.e.tquery.Filter.normalizeFilterExpression(exprs[i]));
+            tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));
       }
     },
 
@@ -42,7 +42,7 @@
       return true;
     }
   };
-  tv.c.ScriptingObjectRegistry.register(
+  tr.c.ScriptingObjectRegistry.register(
       function() {
         var exprs = [];
         for (var i = 0; i < arguments.length; i++) {
diff --git a/trace-viewer/trace_viewer/extras/tquery/filter_any_of.html b/trace-viewer/trace_viewer/extras/tquery/filter_any_of.html
index afffc9b..37a064e 100644
--- a/trace-viewer/trace_viewer/extras/tquery/filter_any_of.html
+++ b/trace-viewer/trace_viewer/extras/tquery/filter_any_of.html
@@ -11,20 +11,20 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function FilterAnyOf(opt_subExpressions) {
-    tv.e.tquery.Filter.call(this);
+    tr.e.tquery.Filter.call(this);
     this.subExpressions = opt_subExpressions || [];
   };
 
   FilterAnyOf.prototype = {
-    __proto__: tv.e.tquery.Filter.prototype,
+    __proto__: tr.e.tquery.Filter.prototype,
 
     set subExpressions(exprs) {
       this.subExpressions_ = [];
       for (var i = 0; i < exprs.length; i++) {
         this.subExpressions_.push(
-            tv.e.tquery.Filter.normalizeFilterExpression(exprs[i]));
+            tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));
       }
     },
 
@@ -42,7 +42,7 @@
       return false;
     }
   };
-  tv.c.ScriptingObjectRegistry.register(
+  tr.c.ScriptingObjectRegistry.register(
       function() {
         var exprs = [];
         for (var i = 0; i < arguments.length; i++) {
diff --git a/trace-viewer/trace_viewer/extras/tquery/filter_has_ancestor.html b/trace-viewer/trace_viewer/extras/tquery/filter_has_ancestor.html
index 33cda0c..0ad397d 100644
--- a/trace-viewer/trace_viewer/extras/tquery/filter_has_ancestor.html
+++ b/trace-viewer/trace_viewer/extras/tquery/filter_has_ancestor.html
@@ -11,16 +11,16 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function FilterHasAncestor(opt_subExpression) {
     this.subExpression = opt_subExpression;
   };
 
   FilterHasAncestor.prototype = {
-    __proto__: tv.e.tquery.Filter.prototype,
+    __proto__: tr.e.tquery.Filter.prototype,
 
     set subExpression(expr) {
-      this.subExpression_ = tv.e.tquery.Filter.normalizeFilterExpression(expr);
+      this.subExpression_ = tr.e.tquery.Filter.normalizeFilterExpression(expr);
     },
 
     get subExpression() {
@@ -38,7 +38,7 @@
       return false;
     }
   };
-  tv.c.ScriptingObjectRegistry.register(
+  tr.c.ScriptingObjectRegistry.register(
       function(subExpression) {
         return new FilterHasAncestor(subExpression);
       },
diff --git a/trace-viewer/trace_viewer/extras/tquery/filter_has_duration.html b/trace-viewer/trace_viewer/extras/tquery/filter_has_duration.html
index c8b91b7..d757a0f 100644
--- a/trace-viewer/trace_viewer/extras/tquery/filter_has_duration.html
+++ b/trace-viewer/trace_viewer/extras/tquery/filter_has_duration.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function FilterHasDuration(minValueOrExpected, opt_maxValue) {
     if (minValueOrExpected !== undefined && opt_maxValue !== undefined) {
       this.minValue = minValueOrExpected;
@@ -22,7 +22,7 @@
   };
 
   FilterHasDuration.prototype = {
-    __proto__: tv.e.tquery.Filter.prototype,
+    __proto__: tr.e.tquery.Filter.prototype,
 
     evaluate: function(context) {
       if (context.event.duration === undefined)
@@ -34,7 +34,7 @@
       return this.matchValue_(context.event.duration, this.expected);
     }
   };
-  tv.c.ScriptingObjectRegistry.register(
+  tr.c.ScriptingObjectRegistry.register(
       function(minValueOrExpected, opt_maxValue) {
         return new FilterHasDuration(minValueOrExpected, opt_maxValue);
       },
diff --git a/trace-viewer/trace_viewer/extras/tquery/filter_has_title.html b/trace-viewer/trace_viewer/extras/tquery/filter_has_title.html
index 4eeee39..50c5bfd 100644
--- a/trace-viewer/trace_viewer/extras/tquery/filter_has_title.html
+++ b/trace-viewer/trace_viewer/extras/tquery/filter_has_title.html
@@ -11,22 +11,22 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function FilterHasTitle(expected) {
-    tv.e.tquery.Filter.call(this);
+    tr.e.tquery.Filter.call(this);
     this.expected = expected;
   }
 
   FilterHasTitle.prototype = {
-    __proto__: tv.e.tquery.Filter.prototype,
+    __proto__: tr.e.tquery.Filter.prototype,
 
     evaluate: function(context) {
       return this.matchValue_(context.event.title, this.expected);
     }
   };
-  tv.c.ScriptingObjectRegistry.register(
+  tr.c.ScriptingObjectRegistry.register(
       function(expected) {
-        var filter = new tv.e.tquery.FilterHasTitle(expected);
+        var filter = new tr.e.tquery.FilterHasTitle(expected);
         return filter;
       },
       {
diff --git a/trace-viewer/trace_viewer/extras/tquery/filter_is_top_level.html b/trace-viewer/trace_viewer/extras/tquery/filter_is_top_level.html
index 975b8b0..e15614f 100644
--- a/trace-viewer/trace_viewer/extras/tquery/filter_is_top_level.html
+++ b/trace-viewer/trace_viewer/extras/tquery/filter_is_top_level.html
@@ -11,16 +11,16 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function FilterIsTopLevel(opt_subExpression) {
     this.subExpression = opt_subExpression;
   }
 
   FilterIsTopLevel.prototype = {
-    __proto__: tv.e.tquery.Filter.prototype,
+    __proto__: tr.e.tquery.Filter.prototype,
 
     set subExpression(expr) {
-      this.subExpression_ = tv.e.tquery.Filter.normalizeFilterExpression(expr);
+      this.subExpression_ = tr.e.tquery.Filter.normalizeFilterExpression(expr);
     },
 
     get subExpression() {
@@ -35,7 +35,7 @@
       return this.subExpression.evaluate(context);
     }
   };
-  tv.c.ScriptingObjectRegistry.register(
+  tr.c.ScriptingObjectRegistry.register(
       function(subExpression) {
         return new FilterIsTopLevel(subExpression);
       },
diff --git a/trace-viewer/trace_viewer/extras/tquery/tquery.html b/trace-viewer/trace_viewer/extras/tquery/tquery.html
index 7edb84b..c3bbb02 100644
--- a/trace-viewer/trace_viewer/extras/tquery/tquery.html
+++ b/trace-viewer/trace_viewer/extras/tquery/tquery.html
@@ -20,9 +20,9 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function TQuery(selectionController) {
-    tv.c.ScriptingObject.call(this);
+    tr.c.ScriptingObject.call(this);
 
     this.selectionController_ = selectionController;
     this.parent_ = undefined;
@@ -32,7 +32,7 @@
   };
 
   TQuery.prototype = {
-    __proto__: tv.c.ScriptingObject.prototype,
+    __proto__: tr.c.ScriptingObject.prototype,
 
     onModelChanged: function() {
       this.selection_ = undefined;
@@ -48,7 +48,7 @@
       var result = new TQuery(this.selectionController_);
       result.parent_ = this;
       result.filterExpression_ =
-          tv.e.tquery.Filter.normalizeFilterExpression(filterExpression);
+          tr.e.tquery.Filter.normalizeFilterExpression(filterExpression);
       return result;
     },
 
@@ -71,14 +71,14 @@
         node = node.parent_;
       }
 
-      var rootTask = new tv.b.Task();
+      var rootTask = new tr.b.Task();
       var lastTask = rootTask;
       for (var i = nodes.length - 1; i >= 0; i--) {
         var node = nodes[i];
         // Reuse any memoized result.
         if (node.selection_ !== undefined)
           continue;
-        node.selection_ = new tv.c.Selection();
+        node.selection_ = new tr.c.Selection();
         if (node.parent_ === undefined) {
           // If this is the root, start by collecting all objects from the
           // selection controller.
@@ -107,7 +107,7 @@
     evaluateFilterExpression_: function(inputSelection, outputSelection) {
       var seenEvents = {};
       inputSelection.forEach(function(event) {
-        var context = new tv.e.tquery.Context();
+        var context = new tr.e.tquery.Context();
         context.event = event;
         this.evaluateFilterExpressionForEvent_(
             context, inputSelection, outputSelection, seenEvents);
@@ -148,7 +148,7 @@
     // Returns a task that fills the given selection with everything reachable
     // by the selection controller.
     selectEverythingAsTask_: function(selection) {
-      var passThroughFilter = new tv.c.Filter();
+      var passThroughFilter = new tr.c.Filter();
       var filterTask =
         this.selectionController.addAllEventsMatchingFilterToSelectionAsTask(
             passThroughFilter, selection);
@@ -158,12 +158,12 @@
     get selection() {
       if (this.selection_ === undefined) {
         var graph = this.createFilterTaskGraph_();
-        tv.b.Task.RunSynchronously(graph.rootTask);
+        tr.b.Task.RunSynchronously(graph.rootTask);
       }
       return this.selection_;
     }
   };
-  tv.c.ScriptingObjectRegistry.register(
+  tr.c.ScriptingObjectRegistry.register(
       new TQuery(),
       {
         name: '$t'
diff --git a/trace-viewer/trace_viewer/extras/tquery/tquery_test.html b/trace-viewer/trace_viewer/extras/tquery/tquery_test.html
index 05f0b5f..ad94f23 100644
--- a/trace-viewer/trace_viewer/extras/tquery/tquery_test.html
+++ b/trace-viewer/trace_viewer/extras/tquery/tquery_test.html
@@ -13,14 +13,14 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.e.tquery', function() {
+tr.exportTo('tr.e.tquery', function() {
   function FakeSelectionController() {
-    tv.b.EventTarget.call(this);
+    tr.b.EventTarget.call(this);
     this.allEvents_ = [];
   }
 
   FakeSelectionController.prototype = {
-    __proto__: tv.b.EventTarget.prototype,
+    __proto__: tr.b.EventTarget.prototype,
 
     get allEvents() {
       return this.allEvents_;
@@ -28,12 +28,12 @@
 
     set allEvents(allEvents) {
       this.allEvents_ = allEvents;
-      var e = new tv.b.Event('model-changed');
+      var e = new tr.b.Event('model-changed');
       this.dispatchEvent(e);
     },
 
     addAllEventsMatchingFilterToSelectionAsTask: function(filter, selection) {
-      return new tv.b.Task(function() {
+      return new tr.b.Task(function() {
         var n = this.allEvents.length;
         for (var i = 0; i < n; i++) {
           this.addSubtreeToSelection_(selection, this.allEvents[i]);
@@ -50,7 +50,7 @@
       }
     },
     showScriptControlSelection: function(selection) {
-      this.selection = new tv.c.Selection();
+      this.selection = new tr.c.Selection();
       this.highlight = selection;
     }
   };
@@ -59,8 +59,8 @@
   };
 });
 
-tv.b.unittest.testSuite(function() {
-  var FakeSelectionController = tv.e.tquery.FakeSelectionController;
+tr.b.unittest.testSuite(function() {
+  var FakeSelectionController = tr.e.tquery.FakeSelectionController;
 
   function createSliceArray(sliceCount) {
     var allEvents = [];
@@ -77,7 +77,7 @@
   }
 
   function getScriptObject(name) {
-    var typeInfos = tv.c.ScriptingObjectRegistry.getAllRegisteredTypeInfos();
+    var typeInfos = tr.c.ScriptingObjectRegistry.getAllRegisteredTypeInfos();
     for (var i = 0; i < typeInfos.length; i++) {
       if (typeInfos[i].metadata.name === name) {
         return typeInfos[i].constructor;
@@ -87,16 +87,16 @@
 
   test('tqueryAsyncSelection', function() {
     var selectionController = createFakeSelectionController_(3);
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.show();
-    tv.b.Task.RunSynchronously(result);
+    tr.b.Task.RunSynchronously(result);
     assert.equal(selectionController.highlight.length, 3);
   });
 
   test('tquerySyncSelection', function() {
     var selectionController = createFakeSelectionController_(3);
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     assert.equal(tquery.selection.length, 3);
 
@@ -108,10 +108,10 @@
 
   test('tqueryPassThroughFiltering', function() {
     var selectionController = new createFakeSelectionController_(3);
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.filter().filter().show();
-    tv.b.Task.RunSynchronously(result);
+    tr.b.Task.RunSynchronously(result);
     assert.equal(selectionController.highlight.length, 3);
   });
 
@@ -123,7 +123,7 @@
         {guid: 2, title: 'b'},
         {guid: 3, title: 'c'}
     ];
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.filter(hasTitle('a')).selection;
     assert.equal(result.length, 1);
@@ -146,7 +146,7 @@
         {guid: 2, title: 'b', subSlices: [{guid: 4}]},
         {guid: 3, title: 'c'}
     ];
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.filter(hasAncestor('b')).selection;
     assert.equal(result.length, 1);
@@ -168,7 +168,7 @@
         {guid: 2, title: 'b1'},
         {guid: 3, title: 'c1'}
     ];
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.filter(allOf('a1')).selection;
     assert.equal(result.length, 1);
@@ -190,7 +190,7 @@
         {guid: 2, title: 'b'},
         {guid: 3, title: 'c'}
     ];
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.filter(anyOf('a', 'b')).selection;
     assert.equal(result.length, 2);
@@ -213,7 +213,7 @@
         {guid: 2, title: 'b', subSlices: [{guid: 4}]},
         {guid: 3, title: 'c'}
     ];
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.filter(isTopLevel()).selection;
     assert.equal(result.length, 3);
@@ -235,7 +235,7 @@
         {guid: 3, title: 'c', duration: 3},
         {guid: 4, title: 'no duration'}
     ];
-    var tquery = new tv.e.tquery.TQuery(selectionController);
+    var tquery = new tr.e.tquery.TQuery(selectionController);
 
     var result = tquery.filter(hasDuration(1.5, 2.5)).selection;
     assert.equal(result.length, 1);
diff --git a/trace-viewer/trace_viewer/core/importer/empty_importer.html b/trace-viewer/trace_viewer/importer/empty_importer.html
similarity index 86%
rename from trace-viewer/trace_viewer/core/importer/empty_importer.html
rename to trace-viewer/trace_viewer/importer/empty_importer.html
index 352f82a..49ac113 100644
--- a/trace-viewer/trace_viewer/core/importer/empty_importer.html
+++ b/trace-viewer/trace_viewer/importer/empty_importer.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/base/base.html">
-<link rel="import" href="/core/importer/importer.html">
+<link rel="import" href="/importer/importer.html">
 
 <script>
 'use strict';
@@ -13,8 +13,8 @@
 /**
  * @fileoverview Base class for trace data importers.
  */
-tv.exportTo('tv.c.importer', function() {
-  var Importer = tv.c.importer.Importer;
+tr.exportTo('tr.importer', function() {
+  var Importer = tr.importer.Importer;
   /**
    * Importer for empty strings and arrays.
    * @constructor
diff --git a/trace-viewer/trace_viewer/core/importer/importer.html b/trace-viewer/trace_viewer/importer/importer.html
similarity index 91%
rename from trace-viewer/trace_viewer/core/importer/importer.html
rename to trace-viewer/trace_viewer/importer/importer.html
index 6f18d43..143906f 100644
--- a/trace-viewer/trace_viewer/core/importer/importer.html
+++ b/trace-viewer/trace_viewer/importer/importer.html
@@ -12,7 +12,7 @@
 /**
  * @fileoverview Base class for trace data importers.
  */
-tv.exportTo('tv.c.importer', function() {
+tr.exportTo('tr.importer', function() {
   function Importer() { }
 
   Importer.prototype = {
@@ -61,10 +61,10 @@
   };
 
 
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
   options.defaultMetadata = {};
   options.mandatoryBaseClass = Importer;
-  tv.b.decorateExtensionRegistry(Importer, options);
+  tr.b.decorateExtensionRegistry(Importer, options);
 
   Importer.findImporterFor = function(eventData) {
     var typeInfo = Importer.findTypeInfoMatching(function(ti) {
diff --git a/trace-viewer/trace_viewer/core/importer/simple_line_reader.html b/trace-viewer/trace_viewer/importer/simple_line_reader.html
similarity index 96%
rename from trace-viewer/trace_viewer/core/importer/simple_line_reader.html
rename to trace-viewer/trace_viewer/importer/simple_line_reader.html
index 1ade622..242b579 100644
--- a/trace-viewer/trace_viewer/core/importer/simple_line_reader.html
+++ b/trace-viewer/trace_viewer/importer/simple_line_reader.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.importer', function() {
+tr.exportTo('tr.importer', function() {
   /**
    * @constructor
    */
diff --git a/trace-viewer/trace_viewer/core/trace_model/alert.html b/trace-viewer/trace_viewer/model/alert.html
similarity index 62%
rename from trace-viewer/trace_viewer/core/trace_model/alert.html
rename to trace-viewer/trace_viewer/model/alert.html
index ed87681..03fa087 100644
--- a/trace-viewer/trace_viewer/core/trace_model/alert.html
+++ b/trace-viewer/trace_viewer/model/alert.html
@@ -4,17 +4,17 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/core/trace_model/timed_event.html">
-<link rel="import" href="/core/trace_model/event_info.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/model/timed_event.html">
+<link rel="import" href="/model/event_info.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   function Alert(info, start, opt_associatedEvents, opt_args) {
-    tv.c.trace_model.TimedEvent.call(this, start);
+    tr.model.TimedEvent.call(this, start);
     this.info = info;
     this.args = opt_args || {};
     this.associatedEvents = opt_associatedEvents || [];
@@ -24,7 +24,7 @@
   }
 
   Alert.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype,
+    __proto__: tr.model.TimedEvent.prototype,
 
     get title() {
       return this.info.title;
@@ -36,21 +36,21 @@
 
     get userFriendlyName() {
       return 'Alert ' + this.title + ' at ' +
-          tv.c.analysis.tsString(this.start);
+          tr.b.units.tsString(this.start);
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       Alert,
       {
         name: 'alert',
         pluralName: 'alerts',
-        singleViewElementName: 'tv-c-a-alert-sub-view',
-        multiViewElementName: 'tv-c-a-alert-sub-view'
+        singleViewElementName: 'tr-c-a-alert-sub-view',
+        multiViewElementName: 'tr-c-a-alert-sub-view'
       });
 
   return {
     Alert: Alert
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/annotation.html b/trace-viewer/trace_viewer/model/annotation.html
similarity index 90%
rename from trace-viewer/trace_viewer/core/trace_model/annotation.html
rename to trace-viewer/trace_viewer/model/annotation.html
index 6bfacbc..03885b4 100644
--- a/trace-viewer/trace_viewer/core/trace_model/annotation.html
+++ b/trace-viewer/trace_viewer/model/annotation.html
@@ -11,7 +11,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * Annotation is a base class that represents all annotation objects that
    * can be drawn on the timeline.
@@ -19,7 +19,7 @@
    * @constructor
    */
   function Annotation() {
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
     this.view_ = undefined;
   };
 
@@ -65,9 +65,9 @@
     }
   };
 
-  var options = new tv.b.ExtensionRegistryOptions(tv.b. BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b. BASIC_REGISTRY_MODE);
   options.mandatoryBaseType = Annotation;
-  tv.b.decorateExtensionRegistry(Annotation, options);
+  tr.b.decorateExtensionRegistry(Annotation, options);
 
   Annotation.addEventListener('will-register', function(e) {
     if (!e.typeInfo.constructor.hasOwnProperty('fromDict'))
diff --git a/trace-viewer/trace_viewer/core/trace_model/annotation_test.html b/trace-viewer/trace_viewer/model/annotation_test.html
similarity index 67%
rename from trace-viewer/trace_viewer/core/trace_model/annotation_test.html
rename to trace-viewer/trace_viewer/model/annotation_test.html
index 705faf1..e5f91a6 100644
--- a/trace-viewer/trace_viewer/core/trace_model/annotation_test.html
+++ b/trace-viewer/trace_viewer/model/annotation_test.html
@@ -8,25 +8,25 @@
 <link rel="import" href="/core/location.html">
 <link rel="import" href="/core/timeline_track_view.html">
 <link rel="import" href="/core/timeline_viewport.html">
-<link rel="import" href="/core/trace_model/comment_box_annotation.html">
-<link rel="import" href="/core/trace_model/rect_annotation.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/trace_model/x_marker_annotation.html">
 <link rel="import" href="/core/test_utils.html">
+<link rel="import" href="/model/comment_box_annotation.html">
+<link rel="import" href="/model/rect_annotation.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/x_marker_annotation.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
 
   function createPopulatedTimeline() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var process = model.getOrCreateProcess(1);
     var thread = process.getOrCreateThread(2);
-    thread.sliceGroup.pushSlice(tv.c.test_utils.newSliceNamed('a', 80, 50));
+    thread.sliceGroup.pushSlice(tr.c.test_utils.newSliceNamed('a', 80, 50));
 
-    var timeline = new tv.c.TimelineTrackView();
-    var vp = new tv.c.TimelineViewport(timeline);
+    var timeline = new tr.c.TimelineTrackView();
+    var vp = new tr.c.TimelineViewport(timeline);
     timeline.model = model;
     timeline.focusElement = timeline;
     timeline.tabIndex = 0;
@@ -38,9 +38,9 @@
   test('rectAnnotation', function() {
     var fakeYComponents1 = [{stableId: '1.2', yPercentOffset: 0.3}];
     var fakeYComponents2 = [{stableId: '1.2', yPercentOffset: 0.9}];
-    var start = new tv.c.Location(50, fakeYComponents1);
-    var end = new tv.c.Location(100, fakeYComponents2);
-    var rectAnnotation = new tv.c.trace_model.RectAnnotation(start, end);
+    var start = new tr.c.Location(50, fakeYComponents1);
+    var end = new tr.c.Location(100, fakeYComponents2);
+    var rectAnnotation = new tr.model.RectAnnotation(start, end);
     assert.equal(rectAnnotation.startLocation, start);
     assert.equal(rectAnnotation.endLocation, end);
 
@@ -50,7 +50,7 @@
   });
 
   test('xMarkerAnnotation', function() {
-    var xMarkerAnnotation = new tv.c.trace_model.XMarkerAnnotation(90);
+    var xMarkerAnnotation = new tr.model.XMarkerAnnotation(90);
     assert.equal(xMarkerAnnotation.timestamp, 90);
 
     var timeline = createPopulatedTimeline();
@@ -61,10 +61,10 @@
 
   test('commentBoxAnnotation', function() {
     var fakeYComponents = [{stableId: '1.2', yPercentOffset: 0.5}];
-    var location = new tv.c.Location(120, fakeYComponents);
+    var location = new tr.c.Location(120, fakeYComponents);
     var text = 'abc';
     var commentBoxAnnotation =
-        new tv.c.trace_model.CommentBoxAnnotation(location, text);
+        new tr.model.CommentBoxAnnotation(location, text);
     assert.equal(commentBoxAnnotation.location, location);
     assert.equal(commentBoxAnnotation.text, text);
 
diff --git a/trace-viewer/trace_viewer/core/trace_model/async_slice.html b/trace-viewer/trace_viewer/model/async_slice.html
similarity index 80%
rename from trace-viewer/trace_viewer/core/trace_model/async_slice.html
rename to trace-viewer/trace_viewer/model/async_slice.html
index 4863be1..40f8395 100644
--- a/trace-viewer/trace_viewer/core/trace_model/async_slice.html
+++ b/trace-viewer/trace_viewer/model/async_slice.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/base/extension_registry.html">
-<link rel="import" href="/core/analysis/util.html">
-<link rel="import" href="/core/trace_model/timed_event.html">
+<link rel="import" href="/base/units/util.html">
+<link rel="import" href="/model/timed_event.html">
 
 <script>
 'use strict';
@@ -15,7 +15,7 @@
 /**
  * @fileoverview Provides the AsyncSlice class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * A AsyncSlice represents an interval of time during which an
    * asynchronous operation is in progress. An AsyncSlice consumes no CPU time
@@ -25,7 +25,7 @@
    */
   function AsyncSlice(category, title, colorId, start, args, duration,
                       opt_isTopLevel, opt_cpuStart, opt_cpuDuration) {
-    tv.c.trace_model.TimedEvent.call(this, start);
+    tr.model.TimedEvent.call(this, start);
 
     this.category = category || '';
     this.title = title;
@@ -36,6 +36,7 @@
     this.didNotFinish = false;
     this.important = false;
     this.subSlices = [];
+    this.parentContainer = undefined;
 
     this.id = undefined;
     this.startThread = undefined;
@@ -45,6 +46,7 @@
 
     this.duration = duration;
 
+
     // TODO(nduca): Forgive me for what I must do.
     this.isTopLevel = (opt_isTopLevel === true);
 
@@ -56,7 +58,7 @@
   };
 
   AsyncSlice.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype,
+    __proto__: tr.model.TimedEvent.prototype,
 
     get analysisTypeName() {
       return this.title;
@@ -68,7 +70,7 @@
 
     get userFriendlyName() {
       return 'Async slice ' + this.title + ' at ' +
-          tv.c.analysis.tsString(this.start);
+          tr.b.units.tsString(this.start);
     },
 
     findDescendentSlice: function(targetTitle) {
@@ -96,21 +98,21 @@
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       AsyncSlice,
       {
         name: 'asyncSlice',
         pluralName: 'asyncSlices',
-        singleViewElementName: 'tv-c-a-single-async-slice-sub-view',
-        multiViewElementName: 'tv-c-a-multi-async-slice-sub-view'
+        singleViewElementName: 'tr-c-a-single-async-slice-sub-view',
+        multiViewElementName: 'tr-c-a-multi-async-slice-sub-view'
       });
 
 
-  var options = new tv.b.ExtensionRegistryOptions(
-      tv.b.TYPE_BASED_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(
+      tr.b.TYPE_BASED_REGISTRY_MODE);
   options.mandatoryBaseClass = AsyncSlice;
   options.defaultConstructor = AsyncSlice;
-  tv.b.decorateExtensionRegistry(AsyncSlice, options);
+  tr.b.decorateExtensionRegistry(AsyncSlice, options);
 
   return {
     AsyncSlice: AsyncSlice
diff --git a/trace-viewer/trace_viewer/core/trace_model/async_slice_group.html b/trace-viewer/trace_viewer/model/async_slice_group.html
similarity index 79%
rename from trace-viewer/trace_viewer/core/trace_model/async_slice_group.html
rename to trace-viewer/trace_viewer/model/async_slice_group.html
index c84dba2..ddb8acf 100644
--- a/trace-viewer/trace_viewer/core/trace_model/async_slice_group.html
+++ b/trace-viewer/trace_viewer/model/async_slice_group.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/async_slice.html">
+<link rel="import" href="/model/async_slice.html">
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/base/range.html">
 
@@ -15,44 +15,44 @@
 /**
  * @fileoverview Provides the AsyncSliceGroup class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * A group of AsyncSlices associated with a thread.
    * @constructor
-   * @extends {tv.c.trace_model.EventContainer}
+   * @extends {tr.model.EventContainer}
    */
-  function AsyncSliceGroup(parentThread, opt_name) {
-    this.parentThread_ = parentThread;
-    this.guid_ = tv.b.GUID.allocate();
+  function AsyncSliceGroup(parentContainer, opt_name) {
+    this.parentContainer_ = parentContainer;
+    this.guid_ = tr.b.GUID.allocate();
     this.slices = [];
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
     this.name_ = opt_name;
     this.viewSubGroups_ = undefined;
   }
 
   AsyncSliceGroup.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+    __proto__: tr.model.EventContainer.prototype,
 
     get guid() {
       return this.guid_;
     },
 
-    get parentThread() {
-      return this.parentThread_;
+    get parentContainer() {
+      return this.parentContainer_;
     },
 
     get model() {
-      return this.parentThread_.parent.model;
+      return this.parentContainer_.parent.model;
     },
 
     get stableId() {
-      return this.parentThread_.stableId + '.AsyncSliceGroup';
+      return this.parentContainer_.stableId + '.AsyncSliceGroup';
     },
 
     getSettingsKey: function() {
       if (!this.name_)
         return undefined;
-      var parentKey = this.parentThread_.getSettingsKey();
+      var parentKey = this.parentContainer_.getSettingsKey();
       if (!parentKey)
         return undefined;
       return parentKey + '.' + this.name_;
@@ -62,7 +62,9 @@
      * Helper function that pushes the provided slice onto the slices array.
      */
     push: function(slice) {
+      slice.parentContainer = this.parentContainer;
       this.slices.push(slice);
+      return slice;
     },
 
     /**
@@ -124,11 +126,11 @@
           var subGroupTitle = slice.viewSubGroupTitle;
           if (!subGroupsByTitle[subGroupTitle]) {
             subGroupsByTitle[subGroupTitle] = new AsyncSliceGroup(
-                this.parentThread_, prefix + subGroupTitle);
+                this.parentContainer_, prefix + subGroupTitle);
           }
-          subGroupsByTitle[subGroupTitle].slices.push(slice);
+          subGroupsByTitle[subGroupTitle].push(slice);
         }
-        this.viewSubGroups_ = tv.b.dictionaryValues(subGroupsByTitle);
+        this.viewSubGroups_ = tr.b.dictionaryValues(subGroupsByTitle);
         this.viewSubGroups_.sort(function(a, b) {
           return a.slices[0].compareTo(b.slices[0]);
         });
@@ -138,7 +140,7 @@
 
     iterateAllEventsInThisContainer: function(eventTypePredicate,
                                               callback, opt_this) {
-      if (eventTypePredicate.call(opt_this, tv.c.trace_model.AsyncSlice)) {
+      if (eventTypePredicate.call(opt_this, tr.model.AsyncSlice)) {
         for (var i = 0; i < this.slices.length; i++) {
           var slice = this.slices[i];
           callback.call(opt_this, slice);
diff --git a/trace-viewer/trace_viewer/model/async_slice_group_test.html b/trace-viewer/trace_viewer/model/async_slice_group_test.html
new file mode 100644
index 0000000..f73a09a
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/async_slice_group_test.html
@@ -0,0 +1,68 @@
+<!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="import" href="/core/test_utils.html">
+<link rel="import" href="/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
+  var Process = tr.model.Process;
+  var Thread = tr.model.Thread;
+  var AsyncSlice = tr.model.AsyncSlice;
+  var AsyncSliceGroup = tr.model.AsyncSliceGroup;
+  var newAsyncSlice = tr.c.test_utils.newAsyncSlice;
+  var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx;
+  var newModel = tr.c.test_utils.newModel;
+
+  test('asyncSliceGroupBounds_Empty', function() {
+    var thread = {};
+    var g = new AsyncSliceGroup(thread);
+    g.updateBounds();
+    assert.isTrue(g.bounds.isEmpty);
+  });
+
+  test('asyncSliceGroupBounds_Basic', function() {
+    var model = new tr.Model();
+    var p1 = new Process(model, 1);
+    var t1 = new Thread(p1, 1);
+    var g = new AsyncSliceGroup(t1);
+    g.push(newAsyncSlice(0, 1, t1, t1));
+    g.push(newAsyncSlice(1, 1.5, t1, t1));
+    assert.equal(g.length, 2);
+    g.updateBounds();
+    assert.equal(g.bounds.min, 0);
+    assert.equal(g.bounds.max, 2.5);
+  });
+
+  test('asyncSliceGroupStableId', function() {
+    var model = new tr.Model();
+    var process = model.getOrCreateProcess(123);
+    var thread = process.getOrCreateThread(456);
+    var group = new AsyncSliceGroup(thread);
+
+    assert.equal(process.stableId, 123);
+    assert.equal(thread.stableId, '123.456');
+    assert.equal(group.stableId, '123.456.AsyncSliceGroup');
+  });
+
+  test('asyncSliceParentContainerSetAtPush', function() {
+    var m = newModel(function(m) {
+      m.process = m.getOrCreateProcess(123);
+      m.thread = m.process.getOrCreateThread(456);
+      m.group = new AsyncSliceGroup(m.thread);
+
+      m.sA = m.group.push(newAsyncSliceEx(
+          { title: 'sA', start: 0.0, duration: 10.0 }));
+    });
+
+    assert.deepEqual(m.sA.parentContainer, m.thread);
+  });
+});
+</script>
+
diff --git a/trace-viewer/trace_viewer/core/trace_model/attribute.html b/trace-viewer/trace_viewer/model/attribute.html
similarity index 97%
rename from trace-viewer/trace_viewer/core/trace_model/attribute.html
rename to trace-viewer/trace_viewer/model/attribute.html
index 2313566..d6f076b 100644
--- a/trace-viewer/trace_viewer/core/trace_model/attribute.html
+++ b/trace-viewer/trace_viewer/model/attribute.html
@@ -13,7 +13,7 @@
 /**
  * @fileoverview Provides the Attribute class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   /**
    * @constructor
@@ -161,9 +161,9 @@
     }
   };
 
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
   options.mandatoryBaseType = Attribute;
-  tv.b.decorateExtensionRegistry(Attribute, options);
+  tr.b.decorateExtensionRegistry(Attribute, options);
 
   Attribute.addEventListener('will-register', function(e) {
     if (!e.typeInfo.constructor.hasOwnProperty('fromDict'))
diff --git a/trace-viewer/trace_viewer/core/trace_model/attribute_test.html b/trace-viewer/trace_viewer/model/attribute_test.html
similarity index 95%
rename from trace-viewer/trace_viewer/core/trace_model/attribute_test.html
rename to trace-viewer/trace_viewer/model/attribute_test.html
index 10a9b87..8e63d86 100644
--- a/trace-viewer/trace_viewer/core/trace_model/attribute_test.html
+++ b/trace-viewer/trace_viewer/model/attribute_test.html
@@ -6,16 +6,16 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/attribute.html">
+<link rel="import" href="/model/attribute.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Attribute = tv.c.trace_model.Attribute;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
-  var StringAttribute = tv.c.trace_model.StringAttribute;
-  var UnknownAttribute = tv.c.trace_model.UnknownAttribute;
+tr.b.unittest.testSuite(function() {
+  var Attribute = tr.model.Attribute;
+  var ScalarAttribute = tr.model.ScalarAttribute;
+  var StringAttribute = tr.model.StringAttribute;
+  var UnknownAttribute = tr.model.UnknownAttribute;
 
   test('findCommonTraits', function() {
     // Empty list.
diff --git a/trace-viewer/trace_viewer/core/trace_model/comment_box_annotation.html b/trace-viewer/trace_viewer/model/comment_box_annotation.html
similarity index 66%
rename from trace-viewer/trace_viewer/core/trace_model/comment_box_annotation.html
rename to trace-viewer/trace_viewer/model/comment_box_annotation.html
index 04251c0..b6a5e9b 100644
--- a/trace-viewer/trace_viewer/core/trace_model/comment_box_annotation.html
+++ b/trace-viewer/trace_viewer/model/comment_box_annotation.html
@@ -6,17 +6,17 @@
 -->
 
 <link rel="import" href="/core/location.html">
-<link rel="import" href="/core/trace_model/annotation.html">
-<link rel="import" href="/core/trace_model/rect_annotation.html">
+<link rel="import" href="/model/annotation.html">
+<link rel="import" href="/model/rect_annotation.html">
 <link rel="import" href="/core/tracks/comment_box_annotation_view.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   function CommentBoxAnnotation(location, text) {
-    tv.c.trace_model.Annotation.apply(this, arguments);
+    tr.model.Annotation.apply(this, arguments);
 
     this.location = location;
     this.text = text;
@@ -25,12 +25,12 @@
   CommentBoxAnnotation.fromDict = function(dict) {
     var args = dict.args;
     var location =
-        new tv.c.Location(args.location.xWorld, args.location.yComponents);
-    return new tv.c.trace_model.CommentBoxAnnotation(location, args.text);
+        new tr.c.Location(args.location.xWorld, args.location.yComponents);
+    return new tr.model.CommentBoxAnnotation(location, args.text);
   };
 
   CommentBoxAnnotation.prototype = {
-    __proto__: tv.c.trace_model.Annotation.prototype,
+    __proto__: tr.model.Annotation.prototype,
 
     onRemove: function() {
       this.view_.removeTextArea();
@@ -47,11 +47,11 @@
     },
 
     createView_: function(viewport) {
-      return new tv.c.annotations.CommentBoxAnnotationView(viewport, this);
+      return new tr.c.annotations.CommentBoxAnnotationView(viewport, this);
     }
   };
 
-  tv.c.trace_model.Annotation.register(
+  tr.model.Annotation.register(
       CommentBoxAnnotation, {typeName: 'comment_box'});
 
   return {
diff --git a/trace-viewer/trace_viewer/core/trace_model/container_memory_dump.html b/trace-viewer/trace_viewer/model/container_memory_dump.html
similarity index 79%
rename from trace-viewer/trace_viewer/core/trace_model/container_memory_dump.html
rename to trace-viewer/trace_viewer/model/container_memory_dump.html
index dda5d4f..8db3e1d 100644
--- a/trace-viewer/trace_viewer/core/trace_model/container_memory_dump.html
+++ b/trace-viewer/trace_viewer/model/container_memory_dump.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/timed_event.html">
+<link rel="import" href="/model/timed_event.html">
 
 <script>
 'use strict';
@@ -13,20 +13,20 @@
 /**
  * @fileoverview Provides the ContainerMemoryDump class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * The ContainerMemoryDump represents an abstract container memory dump.
    * @constructor
    */
   function ContainerMemoryDump(start) {
-    tv.c.trace_model.TimedEvent.call(this, start);
+    tr.model.TimedEvent.call(this, start);
 
     this.memoryAllocatorDumps_ = undefined;
     this.memoryAllocatorDumpsByFullName_ = undefined;
   };
 
   ContainerMemoryDump.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype,
+    __proto__: tr.model.TimedEvent.prototype,
 
     shiftTimestampsForward: function(amount) {
       this.start += amount;
@@ -61,6 +61,15 @@
       }
 
       return this.memoryAllocatorDumpsByFullName_[fullName];
+    },
+
+    aggregateMemoryAllocatorDumpAttributes: function(opt_model) {
+      if (this.memoryAllocatorDumps_ === undefined)
+        return;
+
+      this.memoryAllocatorDumps_.forEach(function(dump) {
+        dump.aggregateAttributes(opt_model);
+      });
     }
   };
 
diff --git a/trace-viewer/trace_viewer/core/trace_model/container_memory_dump_test.html b/trace-viewer/trace_viewer/model/container_memory_dump_test.html
similarity index 82%
rename from trace-viewer/trace_viewer/core/trace_model/container_memory_dump_test.html
rename to trace-viewer/trace_viewer/model/container_memory_dump_test.html
index d78eaba..aafa1cb 100644
--- a/trace-viewer/trace_viewer/core/trace_model/container_memory_dump_test.html
+++ b/trace-viewer/trace_viewer/model/container_memory_dump_test.html
@@ -5,17 +5,17 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/attribute.html">
-<link rel="import" href="/core/trace_model/container_memory_dump.html">
-<link rel="import" href="/core/trace_model/memory_allocator_dump.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/container_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ContainerMemoryDump = tv.c.trace_model.ContainerMemoryDump;
-  var MemoryAllocatorDump = tv.c.trace_model.MemoryAllocatorDump;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
+tr.b.unittest.testSuite(function() {
+  var ContainerMemoryDump = tr.model.ContainerMemoryDump;
+  var MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+  var ScalarAttribute = tr.model.ScalarAttribute;
 
   function setUpParentChildRelationship(parent, child) {
     child.parent = parent;
@@ -41,12 +41,12 @@
     var md = new ContainerMemoryDump(42);
 
     var oilpanDump = new MemoryAllocatorDump(md, 'oilpan');
-    oilpanDump.addAttribute('outer_size', new ScalarAttribute('bytes', 1024));
+    oilpanDump.addAttribute('size', new ScalarAttribute('bytes', 1024));
     oilpanDump.addAttribute('objects_count', new ScalarAttribute('objects', 7));
     oilpanDump.addAttribute('inner_size', new ScalarAttribute('bytes', 768));
 
     var v8Dump = new MemoryAllocatorDump(md, 'v8');
-    v8Dump.addAttribute('outer_size', new ScalarAttribute('bytes', 2048));
+    v8Dump.addAttribute('size', new ScalarAttribute('bytes', 2048));
     v8Dump.addAttribute('objects_count', new ScalarAttribute('objects', 15));
     v8Dump.addAttribute('inner_size', new ScalarAttribute('bytes', 1999));
 
@@ -65,13 +65,13 @@
     var md = new ContainerMemoryDump(42);
 
     var oilpanDump = new MemoryAllocatorDump(md, 'oilpan');
-    oilpanDump.addAttribute('outer_size', new ScalarAttribute('bytes', 1024));
+    oilpanDump.addAttribute('size', new ScalarAttribute('bytes', 1024));
     oilpanDump.addAttribute('objects_count', new ScalarAttribute('objects', 7));
     oilpanDump.addAttribute('inner_size', new ScalarAttribute('bytes', 768));
 
     var oilpanBucket1Dump = new MemoryAllocatorDump(
         md, 'oilpan/bucket1', oilpanDump);
-    oilpanBucket1Dump.addAttribute('outer_size',
+    oilpanBucket1Dump.addAttribute('size',
         new ScalarAttribute('bytes', 512));
     oilpanBucket1Dump.addAttribute('objects_count',
         new ScalarAttribute('objects', 3));
@@ -81,7 +81,7 @@
 
     var oilpanBucket2Dump = new MemoryAllocatorDump(
         md, 'oilpan/bucket2', oilpanDump);
-    oilpanBucket2Dump.addAttribute('outer_size',
+    oilpanBucket2Dump.addAttribute('size',
         new ScalarAttribute('bytes', 512));
     oilpanBucket2Dump.addAttribute('objects_count',
         new ScalarAttribute('objects', 4));
@@ -91,7 +91,7 @@
 
     var oilpanBucket2StringsDump = new MemoryAllocatorDump(
         md, 'oilpan/bucket2/strings', oilpanBucket2Dump);
-    oilpanBucket2StringsDump.addAttribute('outer_size',
+    oilpanBucket2StringsDump.addAttribute('size',
         new ScalarAttribute('bytes', 512));
     oilpanBucket2StringsDump.addAttribute('objects_count',
         new ScalarAttribute('objects', 4));
@@ -100,7 +100,7 @@
     setUpParentChildRelationship(oilpanBucket2Dump, oilpanBucket2StringsDump);
 
     var v8Dump = new MemoryAllocatorDump(md, 'v8');
-    v8Dump.addAttribute('outer_size', new ScalarAttribute('bytes', 2048));
+    v8Dump.addAttribute('size', new ScalarAttribute('bytes', 2048));
     v8Dump.addAttribute('objects_count', new ScalarAttribute('objects', 15));
     v8Dump.addAttribute('inner_size', new ScalarAttribute('bytes', 1999));
 
diff --git a/trace-viewer/trace_viewer/core/trace_model/counter.html b/trace-viewer/trace_viewer/model/counter.html
similarity index 87%
rename from trace-viewer/trace_viewer/core/trace_model/counter.html
rename to trace-viewer/trace_viewer/model/counter.html
index 992ec44..e98dd6d 100644
--- a/trace-viewer/trace_viewer/core/trace_model/counter.html
+++ b/trace-viewer/trace_viewer/model/counter.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/counter_series.html">
-<link rel="import" href="/core/trace_model/event_container.html">
+<link rel="import" href="/model/counter_series.html">
+<link rel="import" href="/model/event_container.html">
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/base/range.html">
 
@@ -16,36 +16,49 @@
 /**
  * @fileoverview Provides the Counter class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   /**
    * Stores all the samples for a given counter.
    * @constructor
    */
   function Counter(parent, id, category, name) {
-    tv.c.trace_model.EventContainer.call(this);
-    this.guid_ = tv.b.GUID.allocate();
+    tr.model.EventContainer.call(this);
+    this.guid_ = tr.b.GUID.allocate();
 
-    this.parent = parent;
-    this.id = id;
-    this.category = category || '';
-    this.name = name;
+    this.parent_ = parent;
+    this.id_ = id;
+    this.category_ = category || '';
+    this.name_ = name;
 
     this.series_ = [];
     this.totals = [];
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
   }
 
   Counter.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+    __proto__: tr.model.EventContainer.prototype,
 
-    /*
-     * @return {Number} A globally unique identifier for this counter.
-     */
     get guid() {
       return this.guid_;
     },
 
+    get parent() {
+      return this.parent_;
+    },
+
+    get id() {
+      return this.id_;
+    },
+
+    get category() {
+      return this.category_;
+    },
+
+    get name() {
+      return this.name_;
+    },
+
     iterateAllEventsInThisContainer: function(eventTypePredicate,
                                               callback, opt_this) {
     },
diff --git a/trace-viewer/trace_viewer/core/trace_model/counter_sample.html b/trace-viewer/trace_viewer/model/counter_sample.html
similarity index 66%
rename from trace-viewer/trace_viewer/core/trace_model/counter_sample.html
rename to trace-viewer/trace_viewer/model/counter_sample.html
index 66b827f..45438fe 100644
--- a/trace-viewer/trace_viewer/core/trace_model/counter_sample.html
+++ b/trace-viewer/trace_viewer/model/counter_sample.html
@@ -5,32 +5,28 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/model/event.html">
 <link rel="import" href="/base/iteration_helpers.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/base/units/util.html">
 <link rel="import" href="/base/sorted_array_utils.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   function CounterSample(series, timestamp, value) {
-    tv.c.trace_model.Event.call(this);
+    tr.model.Event.call(this);
     this.series_ = series;
     this.timestamp_ = timestamp;
     this.value_ = value;
   }
 
   CounterSample.groupByTimestamp = function(samples) {
-    var samplesByTimestamp = {};
-    for (var i = 0; i < samples.length; i++) {
-      var sample = samples[i];
-      var ts = sample.timestamp;
-      if (!samplesByTimestamp[ts])
-        samplesByTimestamp[ts] = [];
-      samplesByTimestamp[ts].push(sample);
-    }
-    var timestamps = tv.b.dictionaryKeys(samplesByTimestamp);
+    var samplesByTimestamp = tr.b.group(samples, function(sample) {
+      return sample.timestamp;
+    });
+
+    var timestamps = tr.b.dictionaryKeys(samplesByTimestamp);
     timestamps.sort();
     var groups = [];
     for (var i = 0; i < timestamps.length; i++) {
@@ -45,7 +41,7 @@
   }
 
   CounterSample.prototype = {
-    __proto__: tv.c.trace_model.Event.prototype,
+    __proto__: tr.model.Event.prototype,
 
     get series() {
       return this.series_;
@@ -68,7 +64,7 @@
     },
 
     getSampleIndex: function() {
-      return tv.b.findLowIndexInSortedArray(
+      return tr.b.findLowIndexInSortedArray(
           this.series.timestamps,
           function(x) { return x; },
           this.timestamp_);
@@ -76,18 +72,18 @@
 
     get userFriendlyName() {
       return 'Counter sample from ' + this.series_.title + ' at ' +
-          tv.c.analysis.tsString(this.timestamp);
+          tr.b.units.tsString(this.timestamp);
     }
   };
 
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       CounterSample,
       {
         name: 'counterSample',
         pluralName: 'counterSamples',
-        singleViewElementName: 'tv-c-counter-sample-sub-view',
-        multiViewElementName: 'tv-c-counter-sample-sub-view'
+        singleViewElementName: 'tr-c-a-counter-sample-sub-view',
+        multiViewElementName: 'tr-c-a-counter-sample-sub-view'
       });
 
   return {
diff --git a/trace-viewer/trace_viewer/core/trace_model/counter_sample_test.html b/trace-viewer/trace_viewer/model/counter_sample_test.html
similarity index 82%
rename from trace-viewer/trace_viewer/core/trace_model/counter_sample_test.html
rename to trace-viewer/trace_viewer/model/counter_sample_test.html
index 1584c0f..527a393 100644
--- a/trace-viewer/trace_viewer/core/trace_model/counter_sample_test.html
+++ b/trace-viewer/trace_viewer/model/counter_sample_test.html
@@ -5,15 +5,15 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/counter.html">
+<link rel="import" href="/model/counter.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Counter = tv.c.trace_model.Counter;
-  var CounterSeries = tv.c.trace_model.CounterSeries;
-  var CounterSample = tv.c.trace_model.CounterSample;
+tr.b.unittest.testSuite(function() {
+  var Counter = tr.model.Counter;
+  var CounterSeries = tr.model.CounterSeries;
+  var CounterSample = tr.model.CounterSample;
 
   test('groupByTimestamp', function() {
     var counter = new Counter();
diff --git a/trace-viewer/trace_viewer/core/trace_model/counter_series.html b/trace-viewer/trace_viewer/model/counter_series.html
similarity index 83%
rename from trace-viewer/trace_viewer/core/trace_model/counter_series.html
rename to trace-viewer/trace_viewer/model/counter_series.html
index 2e2095f..959c1b6 100644
--- a/trace-viewer/trace_viewer/core/trace_model/counter_series.html
+++ b/trace-viewer/trace_viewer/model/counter_series.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/counter_sample.html">
-<link rel="import" href="/core/trace_model/event_container.html">
+<link rel="import" href="/model/counter_sample.html">
+<link rel="import" href="/model/event_container.html">
 
 <script>
 'use strict';
@@ -14,12 +14,12 @@
 /**
  * @fileoverview Provides the CounterSeries class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var CounterSample = tv.c.trace_model.CounterSample;
+tr.exportTo('tr.model', function() {
+  var CounterSample = tr.model.CounterSample;
 
   function CounterSeries(name, color) {
-    tv.c.trace_model.EventContainer.call(this);
-    this.guid_ = tv.b.GUID.allocate();
+    tr.model.EventContainer.call(this);
+    this.guid_ = tr.b.GUID.allocate();
 
     this.name_ = name;
     this.color_ = color;
@@ -33,7 +33,7 @@
   }
 
   CounterSeries.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+    __proto__: tr.model.EventContainer.prototype,
 
     get length() {
       return this.timestamps_.length;
@@ -105,7 +105,7 @@
 
     iterateAllEventsInThisContainer: function(eventTypePredicate,
                                               callback, opt_this) {
-      if (eventTypePredicate.call(opt_this, tv.c.trace_model.CounterSample)) {
+      if (eventTypePredicate.call(opt_this, tr.model.CounterSample)) {
         this.samples_.forEach(callback, opt_this);
       }
     },
diff --git a/trace-viewer/trace_viewer/core/trace_model/counter_test.html b/trace-viewer/trace_viewer/model/counter_test.html
similarity index 90%
rename from trace-viewer/trace_viewer/core/trace_model/counter_test.html
rename to trace-viewer/trace_viewer/model/counter_test.html
index 4f8b22c..2ec5e57 100644
--- a/trace-viewer/trace_viewer/core/trace_model/counter_test.html
+++ b/trace-viewer/trace_viewer/model/counter_test.html
@@ -6,16 +6,16 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/counter.html">
-<link rel="import" href="/core/trace_model/counter_series.html">
+<link rel="import" href="/model/counter.html">
+<link rel="import" href="/model/counter_series.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Counter = tv.c.trace_model.Counter;
-  var CounterSeries = tv.c.trace_model.CounterSeries;
-  var CounterSample = tv.c.trace_model.CounterSample;
+tr.b.unittest.testSuite(function() {
+  var Counter = tr.model.Counter;
+  var CounterSeries = tr.model.CounterSeries;
+  var CounterSample = tr.model.CounterSample;
 
   var createCounterWithTwoSeries = function() {
     var ctr = new Counter(null, 0, '', 'myCounter');
diff --git a/trace-viewer/trace_viewer/core/trace_model/cpu.html b/trace-viewer/trace_viewer/model/cpu.html
similarity index 89%
rename from trace-viewer/trace_viewer/core/trace_model/cpu.html
rename to trace-viewer/trace_viewer/model/cpu.html
index 43cbdb7..0b5adfa 100644
--- a/trace-viewer/trace_viewer/core/trace_model/cpu.html
+++ b/trace-viewer/trace_viewer/model/cpu.html
@@ -6,9 +6,9 @@
 -->
 
 <link rel="import" href="/base/range.html">
-<link rel="import" href="/core/trace_model/counter.html">
-<link rel="import" href="/core/trace_model/cpu_slice.html">
-<link rel="import" href="/core/trace_model/thread_time_slice.html">
+<link rel="import" href="/model/counter.html">
+<link rel="import" href="/model/cpu_slice.html">
+<link rel="import" href="/model/thread_time_slice.html">
 
 <script>
 'use strict';
@@ -16,11 +16,11 @@
 /**
  * @fileoverview Provides the Cpu class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
-  var Counter = tv.c.trace_model.Counter;
-  var Slice = tv.c.trace_model.Slice;
-  var CpuSlice = tv.c.trace_model.CpuSlice;
+  var Counter = tr.model.Counter;
+  var Slice = tr.model.Slice;
+  var CpuSlice = tr.model.CpuSlice;
 
   /**
    * The Cpu represents a Cpu from the kernel's point of view.
@@ -33,7 +33,7 @@
     this.cpuNumber = number;
     this.slices = [];
     this.counters = {};
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
     this.samples_ = undefined; // Set during createSubSlices
 
     // Start timestamp of the last active thread.
@@ -51,11 +51,11 @@
   Cpu.prototype = {
     iterateAllEventsInThisContainer: function(eventTypePredicate,
                                               callback, opt_this) {
-      if (eventTypePredicate.call(opt_this, tv.c.trace_model.CpuSlice))
+      if (eventTypePredicate.call(opt_this, tr.model.CpuSlice))
         this.slices.forEach(callback, opt_this);
 
       if (this.samples_) {
-        if (eventTypePredicate.call(opt_this, tv.c.trace_model.Sample))
+        if (eventTypePredicate.call(opt_this, tr.model.Sample))
           this.samples_.forEach(callback, opt_this);
       }
     },
@@ -134,7 +134,7 @@
      * Returns the index of the slice in the CPU's slices, or undefined.
      */
     indexOf: function(cpuSlice) {
-      var i = tv.b.findLowIndexInSortedArray(
+      var i = tr.b.findLowIndexInSortedArray(
           this.slices,
           function(slice) { return slice.start; },
           cpuSlice.start);
@@ -165,9 +165,9 @@
       }
 
       var duration = end_timestamp - this.lastActiveTimestamp_;
-      var slice = new tv.c.trace_model.CpuSlice(
+      var slice = new tr.model.CpuSlice(
           '', this.lastActiveName_,
-          tv.b.ui.getColorIdForGeneralPurposeString(this.lastActiveName_),
+          tr.b.ui.getColorIdForGeneralPurposeString(this.lastActiveName_),
           this.lastActiveTimestamp_,
           this.lastActiveArgs_,
           duration);
diff --git a/trace-viewer/trace_viewer/core/trace_model/cpu_slice.html b/trace-viewer/trace_viewer/model/cpu_slice.html
similarity index 77%
rename from trace-viewer/trace_viewer/core/trace_model/cpu_slice.html
rename to trace-viewer/trace_viewer/model/cpu_slice.html
index c3abe6e..bc3977b 100644
--- a/trace-viewer/trace_viewer/core/trace_model/cpu_slice.html
+++ b/trace-viewer/trace_viewer/model/cpu_slice.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/base/range.html">
-<link rel="import" href="/core/trace_model/thread_time_slice.html">
+<link rel="import" href="/model/thread_time_slice.html">
 
 <script>
 'use strict';
@@ -14,9 +14,9 @@
 /**
  * @fileoverview Provides the CpuSlice class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
-  var Slice = tv.c.trace_model.Slice;
+  var Slice = tr.model.Slice;
 
   /**
    * A CpuSlice represents a slice of time on a CPU.
@@ -33,7 +33,7 @@
     __proto__: Slice.prototype,
 
     get analysisTypeName() {
-      return 'tv.c.analysis.CpuSlice';
+      return 'tr.c.analysis.CpuSlice';
     },
 
     getAssociatedTimeslice: function() {
@@ -52,13 +52,13 @@
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       CpuSlice,
       {
         name: 'cpuSlice',
         pluralName: 'cpuSlices',
-        singleViewElementName: 'tv-c-single-cpu-slice-sub-view',
-        multiViewElementName: 'tv-c-a-multi-cpu-slice-sub-view'
+        singleViewElementName: 'tr-c-a-single-cpu-slice-sub-view',
+        multiViewElementName: 'tr-c-a-multi-cpu-slice-sub-view'
       });
 
   return {
diff --git a/trace-viewer/trace_viewer/core/trace_model/cpu_test.html b/trace-viewer/trace_viewer/model/cpu_test.html
similarity index 89%
rename from trace-viewer/trace_viewer/core/trace_model/cpu_test.html
rename to trace-viewer/trace_viewer/model/cpu_test.html
index 3e39d46..a968013 100644
--- a/trace-viewer/trace_viewer/core/trace_model/cpu_test.html
+++ b/trace-viewer/trace_viewer/model/cpu_test.html
@@ -6,14 +6,14 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Cpu = tv.c.trace_model.Cpu;
-  var newThreadSlice = tv.c.test_utils.newThreadSlice;
+tr.b.unittest.testSuite(function() {
+  var Cpu = tr.model.Cpu;
+  var newThreadSlice = tr.c.test_utils.newThreadSlice;
 
   test('cpuBounds_Empty', function() {
     var cpu = new Cpu({}, 1);
@@ -24,7 +24,7 @@
 
   test('cpuBounds_OneSlice', function() {
     var cpu = new Cpu({}, 1);
-    cpu.slices.push(tv.c.test_utils.newSlice(1, 3));
+    cpu.slices.push(tr.c.test_utils.newSlice(1, 3));
     cpu.updateBounds();
     assert.equal(cpu.bounds.min, 1);
     assert.equal(cpu.bounds.max, 4);
@@ -40,13 +40,13 @@
   test('shiftTimestampsForward', function() {
     var cpu = new Cpu({}, 1);
     var ctr = cpu.getOrCreateCounter('foo', 'bar');
-    cpu.slices.push(tv.c.test_utils.newSlice(1, 3));
+    cpu.slices.push(tr.c.test_utils.newSlice(1, 3));
     var shiftCount = 0;
     ctr.shiftTimestampsForward = function(ts) {
       if (ts == 0.32)
         shiftCount++;
     };
-    cpu.slices.push(tv.c.test_utils.newSlice(1, 3));
+    cpu.slices.push(tr.c.test_utils.newSlice(1, 3));
     cpu.shiftTimestampsForward(0.32);
     assert.equal(1, shiftCount);
     assert.equal(cpu.slices[0].start, 1.32);
@@ -54,7 +54,7 @@
 
 
   function newCpuSliceNamed(cpu, name, start, duration, opt_thread) {
-    var s = new tv.c.trace_model.CpuSlice(
+    var s = new tr.model.CpuSlice(
         'cat', name, 0, start, {}, duration);
     s.cpu = cpu;
     if (opt_thread)
@@ -63,8 +63,8 @@
   }
 
   test('getTimesliceForCpuSlice', function() {
-    var m = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var m = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var cpu = m.kernel.getOrCreateCpu(1);
     var t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
     t2.timeSlices = [newThreadSlice(t2, SCHEDULING_STATE.RUNNING, 0, 10, cpu),
@@ -88,8 +88,8 @@
   });
 
   test('putToSleepFor', function() {
-    var m = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var m = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var cpu = m.kernel.getOrCreateCpu(1);
 
     var t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
@@ -112,8 +112,8 @@
   });
 
   test('putToSleepForNothing', function() {
-    var m = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var m = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var cpu = m.kernel.getOrCreateCpu(1);
 
     var t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
@@ -129,7 +129,7 @@
   });
 
   test('switchActiveThread', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     var cpu = m.kernel.getOrCreateCpu(1);
 
     cpu.switchActiveThread(5, {}, 0, 'idle thread', {});
diff --git a/trace-viewer/trace_viewer/model/device.html b/trace-viewer/trace_viewer/model/device.html
new file mode 100644
index 0000000..c8acdf4
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/device.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/guid.html">
+<link rel="import" href="/base/range.html">
+<link rel="import" href="/model/event_container.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Device class.
+ */
+tr.exportTo('tr.model', function() {
+
+  /**
+   * Device represents the device-level objects in the model.
+   * @constructor
+     @extends {tr.model.EventContainer}
+   */
+  function Device(model) {
+    if (!model)
+      throw new Error('Must provide a model.');
+
+    tr.model.EventContainer.call(this);
+
+    this.bounds = new tr.b.Range();
+    this.guid = tr.b.GUID.allocate();
+  };
+
+  Device.compare = function(x, y) {
+    return x.guid - y.guid;
+  };
+
+  Device.prototype = {
+    __proto__: tr.model.EventContainer.prototype,
+
+    compareTo: function(that) {
+      return Device.compare(this, that);
+    },
+
+    get userFriendlyName() {
+      return 'Device';
+    },
+
+    get userFriendlyDetails() {
+      return 'Device';
+    },
+
+    get stableId() {
+      return 'Device';
+    },
+
+    getSettingsKey: function() {
+      return 'device';
+    },
+
+    get counters() {
+      return {};
+    },
+
+    updateBounds: function() {
+      this.bounds.reset();
+      // TODO(charliea): Update and add bounds for all children counters
+    },
+
+    shiftTimestampsForward: function(amount) {
+      // TODO(charliea): Shift timestamps for all children
+    },
+
+    addCategoriesToDict: function(categoriesDict) {
+      // TODO(charliea): Add categories for all counters to dictionary
+    },
+
+    iterateAllEventsInThisContainer: function(eventTypePredicate,
+                                              callback, opt_this) {
+    },
+
+    iterateAllChildEventContainers: function(callback, opt_this) {
+      // TODO(charliea): Call callback on all child counters
+    }
+  };
+
+  return {
+    Device: Device
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/event.html b/trace-viewer/trace_viewer/model/event.html
similarity index 88%
rename from trace-viewer/trace_viewer/core/trace_model/event.html
rename to trace-viewer/trace_viewer/model/event.html
index f0d9baf..83dc138 100644
--- a/trace-viewer/trace_viewer/core/trace_model/event.html
+++ b/trace-viewer/trace_viewer/model/event.html
@@ -7,8 +7,8 @@
 
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/base/extension_registry.html">
-<link rel="import" href="/core/trace_model/selectable_item.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/selectable_item.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
@@ -16,9 +16,9 @@
 /**
  * @fileoverview Provides the Event class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var SelectableItem = tv.c.trace_model.SelectableItem;
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.exportTo('tr.model', function() {
+  var SelectableItem = tr.model.SelectableItem;
+  var SelectionState = tr.model.SelectionState;
 
   // Cached values for getCategoryParts.
   var categoryPartsFor = {};
@@ -50,7 +50,7 @@
    */
   function Event() {
     SelectableItem.call(this, this /* modelItem */);
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
     this.selectionState = SelectionState.NONE;
     this.associatedAlerts = [];
     this.info = undefined;
@@ -67,9 +67,9 @@
   // Create the type registry.
   function EventRegistry() {
   }
-  var options = new tv.b.ExtensionRegistryOptions(tv.b.BASIC_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
   options.mandatoryBaseType = Event;
-  tv.b.decorateExtensionRegistry(EventRegistry, options);
+  tr.b.decorateExtensionRegistry(EventRegistry, options);
 
   // Enforce all options objects have the right fields.
   EventRegistry.addEventListener('will-register', function(e) {
@@ -77,7 +77,7 @@
 
     if (metadata.name === undefined)
       throw new Error('Registered events must provide name metadata');
-    var i = tv.b.findFirstInArray(
+    var i = tr.b.findFirstInArray(
       EventRegistry.getAllRegisteredTypeInfos(),
       function(x) { return x.metadata.name === metadata.name; });
     if (i !== undefined)
diff --git a/trace-viewer/trace_viewer/core/trace_model/event_container.html b/trace-viewer/trace_viewer/model/event_container.html
similarity index 97%
rename from trace-viewer/trace_viewer/core/trace_model/event_container.html
rename to trace-viewer/trace_viewer/model/event_container.html
index 254c2f2..1e31b4c 100644
--- a/trace-viewer/trace_viewer/core/trace_model/event_container.html
+++ b/trace-viewer/trace_viewer/model/event_container.html
@@ -13,7 +13,7 @@
 /**
  * @fileoverview Provides the base class for all container classes.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   function EventContainer() {
     this.important = true;
     this.bounds = undefined;
diff --git a/trace-viewer/trace_viewer/core/trace_model/event_info.html b/trace-viewer/trace_viewer/model/event_info.html
similarity index 89%
rename from trace-viewer/trace_viewer/core/trace_model/event_info.html
rename to trace-viewer/trace_viewer/model/event_info.html
index 858ed0f..94f9cfb 100644
--- a/trace-viewer/trace_viewer/core/trace_model/event_info.html
+++ b/trace-viewer/trace_viewer/model/event_info.html
@@ -9,7 +9,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   /**
    * EventInfo is an annotation added to Events in order to document
@@ -28,11 +28,11 @@
     this.title = title;
     this.description = description;
     this.docLinks = docLinks;
-    this.colorId = tv.b.ui.getColorIdForGeneralPurposeString(title);
+    this.colorId = tr.b.ui.getColorIdForGeneralPurposeString(title);
   }
 
   return {
     EventInfo: EventInfo
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/event_test.html b/trace-viewer/trace_viewer/model/event_test.html
similarity index 74%
rename from trace-viewer/trace_viewer/core/trace_model/event_test.html
rename to trace-viewer/trace_viewer/model/event_test.html
index 71d3591..39f122f 100644
--- a/trace-viewer/trace_viewer/core/trace_model/event_test.html
+++ b/trace-viewer/trace_viewer/model/event_test.html
@@ -6,13 +6,13 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/model/event.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Event = tv.c.trace_model.Event;
+tr.b.unittest.testSuite(function() {
+  var Event = tr.model.Event;
 
   test('checkModelItem', function() {
     var event = new Event;
diff --git a/trace-viewer/trace_viewer/core/trace_model/flow_event.html b/trace-viewer/trace_viewer/model/flow_event.html
similarity index 68%
rename from trace-viewer/trace_viewer/core/trace_model/flow_event.html
rename to trace-viewer/trace_viewer/model/flow_event.html
index 70d670b..3a6acba 100644
--- a/trace-viewer/trace_viewer/core/trace_model/flow_event.html
+++ b/trace-viewer/trace_viewer/model/flow_event.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/timed_event.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/model/timed_event.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
@@ -14,7 +14,7 @@
 /**
  * @fileoverview Provides the Flow class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * A Flow represents an interval of time plus parameters associated
    * with that interval.
@@ -22,7 +22,7 @@
    * @constructor
    */
   function FlowEvent(category, id, title, colorId, start, args, opt_duration) {
-    tv.c.trace_model.TimedEvent.call(this, start);
+    tr.model.TimedEvent.call(this, start);
 
     this.category = category || '';
     this.title = title;
@@ -40,21 +40,21 @@
   }
 
   FlowEvent.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype,
+    __proto__: tr.model.TimedEvent.prototype,
 
     get userFriendlyName() {
       return 'Flow event named ' + this.title + ' at ' +
-          tv.c.analysis.tsString(this.timestamp);
+          tr.b.units.tsString(this.timestamp);
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       FlowEvent,
       {
         name: 'flowEvent',
         pluralName: 'flowEvents',
-        singleViewElementName: 'tv-c-single-flow-event-sub-view',
-        multiViewElementName: 'tv-c-multi-flow-event-sub-view'
+        singleViewElementName: 'tr-c-a-single-flow-event-sub-view',
+        multiViewElementName: 'tr-c-a-multi-flow-event-sub-view'
       });
 
   return {
diff --git a/trace-viewer/trace_viewer/core/trace_model/frame.html b/trace-viewer/trace_viewer/model/frame.html
similarity index 82%
rename from trace-viewer/trace_viewer/core/trace_model/frame.html
rename to trace-viewer/trace_viewer/model/frame.html
index 1812fdd..3e8f9e4 100644
--- a/trace-viewer/trace_viewer/core/trace_model/frame.html
+++ b/trace-viewer/trace_viewer/model/frame.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/base/statistics.html">
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/model/event.html">
 <link rel="import" href="/base/ui/color_scheme.html">
 
 <script>
@@ -17,8 +17,8 @@
  * Because a frame is produced by multiple threads, it does not inherit from
  * TimedEvent, and has no duration.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var Statistics = tv.b.Statistics;
+tr.exportTo('tr.model', function() {
+  var Statistics = tr.b.Statistics;
 
   var FRAME_PERF_CLASS = {
     GOOD: 'good',
@@ -34,7 +34,7 @@
    * for each thread, describing the critical path of the frame.
    */
   function Frame(associatedEvents, threadTimeRanges, opt_args) {
-    tv.c.trace_model.Event.call(this);
+    tr.model.Event.call(this);
 
     this.threadTimeRanges = threadTimeRanges;
     this.associatedEvents = associatedEvents;
@@ -52,10 +52,10 @@
   };
 
   Frame.prototype = {
-    __proto__: tv.c.trace_model.Event.prototype,
+    __proto__: tr.model.Event.prototype,
 
     set perfClass(perfClass) {
-      this.colorId = tv.b.ui.getColorIdForReservedName(perfClass);
+      this.colorId = tr.b.ui.getColorIdForReservedName(perfClass);
       this.perfClass_ = perfClass;
     },
 
@@ -79,13 +79,13 @@
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       Frame,
       {
         name: 'frame',
         pluralName: 'frames',
-        singleViewElementName: 'tv-c-single-frame-sub-view',
-        multiViewElementName: 'tv-c-multi-frame-sub-view'
+        singleViewElementName: 'tr-c-a-single-frame-sub-view',
+        multiViewElementName: 'tr-c-a-multi-frame-sub-view'
       });
 
   return {
diff --git a/trace-viewer/trace_viewer/model/global_memory_dump.html b/trace-viewer/trace_viewer/model/global_memory_dump.html
new file mode 100644
index 0000000..1daaf82
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/global_memory_dump.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/model/container_memory_dump.html">
+<link rel="import" href="/base/units/util.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the GlobalMemoryDump class.
+ */
+tr.exportTo('tr.model', function() {
+  /**
+   * The GlobalMemoryDump represents a simultaneous memory dump of all
+   * processes.
+   * @constructor
+   */
+  function GlobalMemoryDump(model, start) {
+    tr.model.ContainerMemoryDump.call(this, start);
+    this.model = model;
+    this.processMemoryDumps = {};
+  }
+
+  GlobalMemoryDump.prototype = {
+    __proto__: tr.model.ContainerMemoryDump.prototype,
+
+    get userFriendlyName() {
+      return 'Global memory dump ' + ' at ' +
+          tr.b.units.tsString(this.start);
+    },
+
+    calculateGraphAttributes: function() {
+      // TODO(petrcermak): Calculate sizes using the graph.
+
+      this.aggregateMemoryAllocatorDumpAttributes(this.model);
+      tr.b.iterItems(this.processMemoryDumps, function(pid, dump) {
+        dump.aggregateMemoryAllocatorDumpAttributes(this.model);
+      }, this);
+
+      // TODO(petrcermak): Consider factoring out all the finalization code and
+      // constants to a single file.
+      tr.b.iterItems(this.processMemoryDumps, function(pid, dump) {
+        dump.discountTracingOverhead(this.model);
+      }, this);
+    }
+  };
+
+  tr.model.EventRegistry.register(
+      GlobalMemoryDump,
+      {
+        name: 'globalMemoryDump',
+        pluralName: 'globalMemoryDumps',
+        singleViewElementName: 'tr-c-a-single-global-memory-dump-sub-view',
+        multiViewElementName: 'tr-c-a-multi-global-memory-dump-sub-view'
+      });
+
+  return {
+    GlobalMemoryDump: GlobalMemoryDump
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/instant_event.html b/trace-viewer/trace_viewer/model/instant_event.html
similarity index 78%
rename from trace-viewer/trace_viewer/core/trace_model/instant_event.html
rename to trace-viewer/trace_viewer/model/instant_event.html
index dffc983..df72ede 100644
--- a/trace-viewer/trace_viewer/core/trace_model/instant_event.html
+++ b/trace-viewer/trace_viewer/model/instant_event.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/timed_event.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/model/timed_event.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
@@ -14,14 +14,14 @@
 /**
  * @fileoverview Provides the InstantEvent class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   var InstantEventType = {
     GLOBAL: 1,
     PROCESS: 2
   };
 
   function InstantEvent(category, title, colorId, start, args) {
-    tv.c.trace_model.TimedEvent.call(this);
+    tr.model.TimedEvent.call(this);
 
     this.category = category || '';
     this.title = title;
@@ -33,7 +33,7 @@
   };
 
   InstantEvent.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype
+    __proto__: tr.model.TimedEvent.prototype
   };
 
   function GlobalInstantEvent(category, title, colorId, start, args) {
@@ -63,13 +63,13 @@
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       InstantEvent,
       {
         name: 'instantEvent',
         pluralName: 'instantEvents',
-        singleViewElementName: 'tv-c-single-instant-event-sub-view',
-        multiViewElementName: 'tv-c-multi-instant-event-sub-view'
+        singleViewElementName: 'tr-c-a-single-instant-event-sub-view',
+        multiViewElementName: 'tr-c-a-multi-instant-event-sub-view'
       });
 
   return {
diff --git a/trace-viewer/trace_viewer/core/trace_model/interaction_record.html b/trace-viewer/trace_viewer/model/interaction_record.html
similarity index 60%
rename from trace-viewer/trace_viewer/core/trace_model/interaction_record.html
rename to trace-viewer/trace_viewer/model/interaction_record.html
index 1c1c916..79b4860 100644
--- a/trace-viewer/trace_viewer/core/trace_model/interaction_record.html
+++ b/trace-viewer/trace_viewer/model/interaction_record.html
@@ -4,15 +4,15 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/core/trace_model/timed_event.html">
-<link rel="import" href="/core/analysis/util.html">
+<link rel="import" href="/model/timed_event.html">
+<link rel="import" href="/base/units/util.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   function InteractionRecord(title, colorId, start, duration) {
-    tv.c.trace_model.TimedEvent.call(this, start);
+    tr.model.TimedEvent.call(this, start);
     this.title = title;
     this.colorId = colorId;
     this.duration = duration;
@@ -20,7 +20,7 @@
     this.associatedEvents = [];
   }
   InteractionRecord.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype,
+    __proto__: tr.model.TimedEvent.prototype,
 
     get subSlices() {
       return [];
@@ -28,21 +28,21 @@
 
     get userFriendlyName() {
       return this.title + ' interaction at ' +
-          tv.c.analysis.tsString(this.start);
+          tr.b.units.tsString(this.start);
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       InteractionRecord,
       {
         name: 'interaction',
         pluralName: 'interactions',
-        singleViewElementName: 'tv-c-single-interaction-record-sub-view',
-        multiViewElementName: 'tv-c-multi-interaction-record-sub-view'
+        singleViewElementName: 'tr-c-a-single-interaction-record-sub-view',
+        multiViewElementName: 'tr-c-a-multi-interaction-record-sub-view'
       });
 
   return {
     InteractionRecord: InteractionRecord
   };
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/kernel.html b/trace-viewer/trace_viewer/model/kernel.html
similarity index 88%
rename from trace-viewer/trace_viewer/core/trace_model/kernel.html
rename to trace-viewer/trace_viewer/model/kernel.html
index 847b8d2..7dcca70 100644
--- a/trace-viewer/trace_viewer/core/trace_model/kernel.html
+++ b/trace-viewer/trace_viewer/model/kernel.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/cpu.html">
-<link rel="import" href="/core/trace_model/process_base.html">
+<link rel="import" href="/model/cpu.html">
+<link rel="import" href="/model/process_base.html">
 <link rel="import" href="/base/iteration_helpers.html">
 
 <script>
@@ -15,19 +15,17 @@
 /**
  * @fileoverview Provides the Process class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var Cpu = tv.c.trace_model.Cpu;
-  var ProcessBase = tv.c.trace_model.ProcessBase;
+tr.exportTo('tr.model', function() {
+  var Cpu = tr.model.Cpu;
+  var ProcessBase = tr.model.ProcessBase;
 
   /**
-   * The Kernel represents kernel-level objects in the
-   * model.
+   * The Kernel represents kernel-level objects in the model.
    * @constructor
    */
   function Kernel(model) {
-    if (model === undefined)
-      throw new Error('model must be provided');
     ProcessBase.call(this, model);
+
     this.cpus = {};
     this.softwareMeasuredCpuCount_ = undefined;
   };
@@ -90,7 +88,7 @@
      * software measured cpu count.
      */
     get bestGuessAtCpuCount() {
-      var realCpuCount = tv.b.dictionaryLength(this.cpus);
+      var realCpuCount = tr.b.dictionaryLength(this.cpus);
       if (realCpuCount !== 0)
         return realCpuCount;
       return this.softwareMeasuredCpuCount;
diff --git a/trace-viewer/trace_viewer/core/trace_model/kernel_test.html b/trace-viewer/trace_viewer/model/kernel_test.html
similarity index 76%
rename from trace-viewer/trace_viewer/core/trace_model/kernel_test.html
rename to trace-viewer/trace_viewer/model/kernel_test.html
index 7455128..040096f 100644
--- a/trace-viewer/trace_viewer/core/trace_model/kernel_test.html
+++ b/trace-viewer/trace_viewer/model/kernel_test.html
@@ -5,22 +5,22 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/trace_model/kernel.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/kernel.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('bestGuessAtCpuCountWithNoData', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([], false, false, function() {
     });
     assert.isUndefined(m.kernel.bestGuessAtCpuCount);
   });
 
   test('bestGuessAtCpuCountWithCpuData', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([], false, false, function() {
       var c1 = m.kernel.getOrCreateCpu(1);
       var c2 = m.kernel.getOrCreateCpu(2);
@@ -29,7 +29,7 @@
   });
 
   test('bestGuessAtCpuCountWithSoftwareCpuCount', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([], false, false, function() {
       m.kernel.softwareMeasuredCpuCount = 2;
     });
@@ -37,23 +37,23 @@
   });
 
   test('kernelStableId', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
 
     assert.equal(model.kernel.stableId, 'Kernel');
   });
 
   test('kernelTimeShifting', function() {
-    var importOptions = new tv.c.ImportOptions();
+    var importOptions = new tr.ImportOptions();
     importOptions.shiftWorldToZero = true;
     importOptions.pruneEmptyContainers = false;
     importOptions.customizeModelCallback = function(m) {
       var ctr = m.kernel.getOrCreateCounter('cat', 'ctr');
-      var c0 = new tv.c.trace_model.CounterSeries('a', 0);
+      var c0 = new tr.model.CounterSeries('a', 0);
       ctr.addSeries(c0);
       c0.addCounterSample(100, 5);
       c0.addCounterSample(200, 5);
     };
-    var m = new tv.c.TraceModel([], importOptions);
+    var m = new tr.Model([], importOptions);
     var ctr = m.kernel.counters['cat.ctr'];
     assert.equal(ctr.series[0].samples[0].timestamp, 0);
     ctr.series[0].samples[0].ts == 100;
diff --git a/trace-viewer/trace_viewer/core/trace_model/memory_allocator_dump.html b/trace-viewer/trace_viewer/model/memory_allocator_dump.html
similarity index 87%
rename from trace-viewer/trace_viewer/core/trace_model/memory_allocator_dump.html
rename to trace-viewer/trace_viewer/model/memory_allocator_dump.html
index 341c192..c8a09b8 100644
--- a/trace-viewer/trace_viewer/core/trace_model/memory_allocator_dump.html
+++ b/trace-viewer/trace_viewer/model/memory_allocator_dump.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/attribute.html">
+<link rel="import" href="/model/attribute.html">
 
 <script>
 'use strict';
@@ -13,7 +13,7 @@
 /**
  * @fileoverview Provides the MemoryAllocatorDump class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * @constructor
    */
@@ -54,17 +54,17 @@
 
       this.children.forEach(function(child) {
         child.aggregateAttributes(opt_model);
-        tv.b.iterItems(child.attributes, function(name) {
+        tr.b.iterItems(child.attributes, function(name) {
           attributes[name] = true;
         }, this);
       }, this);
 
-      tv.b.iterItems(attributes, function(name) {
+      tr.b.iterItems(attributes, function(name) {
         var childAttributes = this.children.map(function(child) {
           return child.attributes[name];
         }, this);
         var currentAttribute = this.attributes[name];
-        this.attributes[name] = tv.c.trace_model.Attribute.aggregate(
+        this.attributes[name] = tr.model.Attribute.aggregate(
             childAttributes, currentAttribute, opt_model);
       }, this);
     }
diff --git a/trace-viewer/trace_viewer/core/trace_model/memory_allocator_dump_test.html b/trace-viewer/trace_viewer/model/memory_allocator_dump_test.html
similarity index 76%
rename from trace-viewer/trace_viewer/core/trace_model/memory_allocator_dump_test.html
rename to trace-viewer/trace_viewer/model/memory_allocator_dump_test.html
index 669c7d5..2e57b09 100644
--- a/trace-viewer/trace_viewer/core/trace_model/memory_allocator_dump_test.html
+++ b/trace-viewer/trace_viewer/model/memory_allocator_dump_test.html
@@ -5,18 +5,18 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/attribute.html">
-<link rel="import" href="/core/trace_model/container_memory_dump.html">
-<link rel="import" href="/core/trace_model/memory_allocator_dump.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/container_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ContainerMemoryDump = tv.c.trace_model.ContainerMemoryDump;
-  var MemoryAllocatorDump = tv.c.trace_model.MemoryAllocatorDump;
-  var MemoryAllocatorDumpLink = tv.c.trace_model.MemoryAllocatorDumpLink;
-  var ScalarAttribute = tv.c.trace_model.ScalarAttribute;
+tr.b.unittest.testSuite(function() {
+  var ContainerMemoryDump = tr.model.ContainerMemoryDump;
+  var MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+  var MemoryAllocatorDumpLink = tr.model.MemoryAllocatorDumpLink;
+  var ScalarAttribute = tr.model.ScalarAttribute;
 
   function setUpParentChildRelationship(parent, child) {
     child.parent = parent;
@@ -31,7 +31,7 @@
 
     var oilpanBucket1Dump = new MemoryAllocatorDump(
         md, 'oilpan/bucket1', oilpanDump);
-    oilpanBucket1Dump.addAttribute('outer_size',
+    oilpanBucket1Dump.addAttribute('size',
         new ScalarAttribute('bytes', 512));
     oilpanBucket1Dump.addAttribute('objects_count',
         new ScalarAttribute('objects', 3));
@@ -45,7 +45,7 @@
 
     var oilpanBucket2StringsDump = new MemoryAllocatorDump(
         md, 'oilpan/bucket2/strings', oilpanBucket2Dump);
-    oilpanBucket2StringsDump.addAttribute('outer_size',
+    oilpanBucket2StringsDump.addAttribute('size',
         new ScalarAttribute('bytes', 512));
     oilpanBucket2StringsDump.addAttribute('objects_count',
         new ScalarAttribute('objects', 4));
@@ -58,19 +58,19 @@
     // oilpan has *some* attributes aggregated.
     assert.equal(oilpanDump.attributes['objects_count'].value, 7);
     assert.equal(oilpanDump.attributes['inner_size'].value, 768);
-    assert.equal(oilpanDump.attributes['outer_size'].value, 1024);
+    assert.equal(oilpanDump.attributes['size'].value, 1024);
 
     // oilpan/bucket2 has *all* attributes aggregated.
     assert.equal(oilpanBucket2Dump.attributes['objects_count'].value,
         4);
     assert.equal(oilpanBucket2Dump.attributes['inner_size'].value, 512);
-    assert.equal(oilpanBucket2Dump.attributes['outer_size'].value, 512);
+    assert.equal(oilpanBucket2Dump.attributes['size'].value, 512);
 
     // oilpan/bucket2/strings has *no* attributes aggregated.
     assert.equal(oilpanBucket2StringsDump.attributes[
         'objects_count'].value, 4);
     assert.equal(oilpanBucket2StringsDump.attributes['inner_size'].value, 512);
-    assert.equal(oilpanBucket2StringsDump.attributes['outer_size'].value, 512);
+    assert.equal(oilpanBucket2StringsDump.attributes['size'].value, 512);
   });
 
   test('memoryAllocatorDumpLink_instantiate', function() {
diff --git a/trace-viewer/trace_viewer/core/trace_model/trace_model.html b/trace-viewer/trace_viewer/model/model.html
similarity index 86%
rename from trace-viewer/trace_viewer/core/trace_model/trace_model.html
rename to trace-viewer/trace_viewer/model/model.html
index ce2db10..39c6c4a 100644
--- a/trace-viewer/trace_viewer/core/trace_model/trace_model.html
+++ b/trace-viewer/trace_viewer/model/model.html
@@ -12,24 +12,26 @@
 <link rel="import" href="/base/ui/overlay.html">
 <link rel="import" href="/core/filter.html">
 <link rel="import" href="/core/auditor.html">
-<link rel="import" href="/core/importer/empty_importer.html">
-<link rel="import" href="/core/importer/importer.html">
-<link rel="import" href="/core/trace_model/kernel.html">
-<link rel="import" href="/core/trace_model/process.html">
-<link rel="import" href="/core/trace_model/sample.html">
-<link rel="import" href="/core/trace_model/stack_frame.html">
-<link rel="import" href="/core/trace_model/instant_event.html">
-<link rel="import" href="/core/trace_model/flow_event.html">
-<link rel="import" href="/core/trace_model/global_memory_dump.html">
-<link rel="import" href="/core/trace_model/process_memory_dump.html">
-<link rel="import" href="/core/trace_model/alert.html">
-<link rel="import" href="/core/trace_model/interaction_record.html">
+<link rel="import" href="/importer/empty_importer.html">
+<link rel="import" href="/importer/importer.html">
+<link rel="import" href="/model/device.html">
+<link rel="import" href="/model/kernel.html">
+<link rel="import" href="/model/process.html">
+<link rel="import" href="/model/sample.html">
+<link rel="import" href="/model/stack_frame.html">
+<link rel="import" href="/model/instant_event.html">
+<link rel="import" href="/model/flow_event.html">
+<link rel="import" href="/model/global_memory_dump.html">
+<link rel="import" href="/model/process_memory_dump.html">
+<link rel="import" href="/model/alert.html">
+<link rel="import" href="/model/interaction_record.html">
+<link rel="import" href="/model/model_indices.html">
 
 <script>
 'use strict';
 
 /**
- * @fileoverview TraceModel is a parsed representation of the
+ * @fileoverview Model is a parsed representation of the
  * TraceEvents obtained from base/trace_event in which the begin-end
  * tokens are converted into a hierarchy of processes, threads,
  * subrows, and slices.
@@ -44,16 +46,17 @@
  * nesting tasks.
  *
  */
-tv.exportTo('tv.c', function() {
-  var Importer = tv.c.importer.Importer;
-  var Process = tv.c.trace_model.Process;
-  var Kernel = tv.c.trace_model.Kernel;
-  var GlobalMemoryDump = tv.c.trace_model.GlobalMemoryDump;
-  var GlobalInstantEvent = tv.c.trace_model.GlobalInstantEvent;
-  var FlowEvent = tv.c.trace_model.FlowEvent;
-  var Alert = tv.c.trace_model.Alert;
-  var InteractionRecord = tv.c.trace_model.InteractionRecord;
-  var Sample = tv.c.trace_model.Sample;
+tr.exportTo('tr', function() {
+  var Importer = tr.importer.Importer;
+  var Process = tr.model.Process;
+  var Device = tr.model.Device;
+  var Kernel = tr.model.Kernel;
+  var GlobalMemoryDump = tr.model.GlobalMemoryDump;
+  var GlobalInstantEvent = tr.model.GlobalInstantEvent;
+  var FlowEvent = tr.model.FlowEvent;
+  var Alert = tr.model.Alert;
+  var InteractionRecord = tr.model.InteractionRecord;
+  var Sample = tr.model.Sample;
 
   function ImportOptions() {
     this.shiftWorldToZero = true;
@@ -64,7 +67,7 @@
     // finalized.
     this.customizeModelCallback = undefined;
 
-    var auditorTypes = tv.c.Auditor.getAllRegisteredTypeInfos();
+    var auditorTypes = tr.c.Auditor.getAllRegisteredTypeInfos();
     this.auditorConstructors = auditorTypes.map(function(typeInfo) {
       return typeInfo.constructor;
     });
@@ -99,22 +102,23 @@
   /**
    * Builds a model from an array of TraceEvent objects.
    * @param {Object=} opt_eventData Data from a single trace to be imported into
-   *     the new model. See TraceModel.importTraces for details on how to
+   *     the new model. See Model.importTraces for details on how to
    *     import multiple traces at once.
    * @param {ImportOptions=} opt_options Options for the import.
    * @constructor
    */
-  function TraceModel(opt_eventData, opt_options) {
-    tv.c.trace_model.EventContainer.call(this);
-    tv.b.EventTarget.decorate(this);
+  function Model(opt_eventData, opt_options) {
+    tr.model.EventContainer.call(this);
+    tr.b.EventTarget.decorate(this);
 
     this.faviconHue = 'blue'; // Should be a key from favicons.html
 
+    this.device = new Device(this);
     this.kernel = new Kernel(this);
     this.processes = {};
     this.metadata = [];
     this.categories = [];
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
     this.instantEvents = [];
     this.flowEvents = [];
     this.clockSyncRecords = [];
@@ -125,7 +129,7 @@
     this.alerts = [];
     this.interaction_records = [];
 
-    this.flowIntervalTree = new tv.b.IntervalTree(
+    this.flowIntervalTree = new tr.b.IntervalTree(
         function(f) { return f.start; },
         function(f) { return f.end; });
 
@@ -136,13 +140,14 @@
     this.importWarnings_ = [];
     this.reportedImportWarnings_ = {};
 
+    this.modelIndices = undefined;
     var options = ImportOptions.fromArguments(arguments, 1);
     if (opt_eventData)
       this.importTraces([opt_eventData], options);
   }
 
-  TraceModel.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+  Model.prototype = {
+    __proto__: tr.model.EventContainer.prototype,
 
     iterateAllEventsInThisContainer: function(eventTypePredicate,
                                               callback, opt_this) {
@@ -166,13 +171,14 @@
     },
 
     iterateAllChildEventContainers: function(callback, opt_this) {
+      callback.call(opt_this, this.device);
       callback.call(opt_this, this.kernel);
       for (var pid in this.processes)
         callback.call(opt_this, this.processes[pid]);
     },
 
     /**
-     * Some objects in the model can persist their state in TraceModelSettings.
+     * Some objects in the model can persist their state in ModelSettings.
      *
      * This iterates through them.
      */
@@ -261,6 +267,7 @@
      */
     updateCategories_: function() {
       var categoriesDict = {};
+      this.device.addCategoriesToDict(categoriesDict);
       this.kernel.addCategoriesToDict(categoriesDict);
       for (var pid in this.processes)
         this.processes[pid].addCategoriesToDict(categoriesDict);
@@ -301,7 +308,9 @@
     getAllCounters: function() {
       var counters = [];
       counters.push.apply(
-          counters, tv.b.dictionaryValues(this.kernel.counters));
+          counters, tr.b.dictionaryValues(this.device.counters));
+      counters.push.apply(
+          counters, tr.b.dictionaryValues(this.kernel.counters));
       for (var pid in this.processes) {
         var process = this.processes[pid];
         for (var tid in process.counters) {
@@ -320,17 +329,17 @@
         throw new Error('Annotation with undefined guid given');
 
       this.annotationsByGuid_[annotation.guid] = annotation;
-      tv.b.dispatchSimpleEvent(this, 'annotationChange');
+      tr.b.dispatchSimpleEvent(this, 'annotationChange');
     },
 
     removeAnnotation: function(annotation) {
       this.annotationsByGuid_[annotation.guid].onRemove();
       delete this.annotationsByGuid_[annotation.guid];
-      tv.b.dispatchSimpleEvent(this, 'annotationChange');
+      tr.b.dispatchSimpleEvent(this, 'annotationChange');
     },
 
     getAllAnnotations: function() {
-      return tv.b.dictionaryValues(this.annotationsByGuid_);
+      return tr.b.dictionaryValues(this.annotationsByGuid_);
     },
 
     /**
@@ -351,7 +360,7 @@
     },
 
     createImporter_: function(eventData) {
-      var importerConstructor = tv.c.importer.Importer.findImporterFor(
+      var importerConstructor = tr.importer.Importer.findImporterFor(
           eventData);
 
       // TODO(kphanee): Throwing same Error at 2 places. Lets try to avoid it!
@@ -389,7 +398,7 @@
           progressMeter,
           traces,
           options);
-      tv.b.Task.RunSynchronously(task);
+      tr.b.Task.RunSynchronously(task);
     },
 
     /**
@@ -400,7 +409,7 @@
     importTracesWithProgressDialog: function(traces, opt_options) {
       var options = ImportOptions.fromArguments(arguments, 1);
 
-      var overlay = tv.b.ui.Overlay();
+      var overlay = tr.b.ui.Overlay();
       overlay.title = 'Importing...';
       overlay.userCanClose = false;
       overlay.msgEl = document.createElement('div');
@@ -415,7 +424,7 @@
           overlay,
           traces,
           options);
-      var promise = tv.b.Task.RunWhenIdle(task);
+      var promise = tr.b.Task.RunWhenIdle(task);
       promise.then(
           function() {
             overlay.visible = false;
@@ -453,7 +462,7 @@
       // Just some simple setup. It is useful to have a nop first
       // task so that we can set up the lastTask = lastTask.after()
       // pattern that follows.
-      var importTask = new tv.b.Task(function() {
+      var importTask = new tr.b.Task(function() {
         progressMeter.update('I will now import your traces for you...');
       }, this);
       var lastTask = importTask;
@@ -623,14 +632,22 @@
           this.processes[pid].autoDeleteObjects(this.bounds.max);
       }, this);
 
-      // Finalize global and process memory dumps.
+      // Sort global and process memory dumps.
       lastTask = lastTask.after(function() {
-        progressMeter.update('Finalizing memory dumps...');
+        progressMeter.update('Sorting memory dumps...');
         this.globalMemoryDumps.sort(function(x, y) {
           return x.start - y.start;
         });
         for (var pid in this.processes)
-          this.processes[pid].finalizeMemoryDumps();
+          this.processes[pid].sortMemoryDumps();
+      }, this);
+
+      // Calculate memory dump graph attributes.
+      lastTask = lastTask.after(function() {
+        progressMeter.update('Calculating memory dump graph attributes...');
+        this.globalMemoryDumps.forEach(function(dump) {
+          dump.calculateGraphAttributes();
+        });
       }, this);
 
       // Run initializers.
@@ -640,6 +657,12 @@
           this.processes[pid].initializeObjects();
       }, this);
 
+      // Build event indices mapping from an event id to all flow events.
+      lastTask = lastTask.after(function() {
+        progressMeter.update('Building flow event indices...');
+        this.modelIndices = new tr.model.ModelIndices(this);
+      }, this);
+
       // Run audits.
       lastTask = lastTask.after(function() {
         progressMeter.update('Running auditors...');
@@ -694,7 +717,7 @@
   return {
     ImportOptions: ImportOptions,
     ClockSyncRecord: ClockSyncRecord,
-    TraceModel: TraceModel
+    Model: Model
   };
 });
 </script>
diff --git a/trace-viewer/trace_viewer/model/model_indices.html b/trace-viewer/trace_viewer/model/model_indices.html
new file mode 100644
index 0000000..0b94d49
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/model_indices.html
@@ -0,0 +1,55 @@
+<!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="import" href="/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Event Index class.
+ */
+tr.exportTo('tr.model', function() {
+  /**
+   * A Event Index maps an id to all the events that have that particular id
+   *
+   * @constructor
+   */
+  function ModelIndices(model) {
+    // For now the only indices we construct are for flowEvents
+    this.flowEventsById_ = {};
+    model.flowEvents.forEach(function(fe) {
+      if (fe.id !== undefined) {
+        if (!this.flowEventsById_.hasOwnProperty(fe.id)) {
+          this.flowEventsById_[fe.id] = new Array();
+        }
+        this.flowEventsById_[fe.id].push(fe);
+      }
+    }, this);
+  }
+
+  ModelIndices.prototype = {
+    addEventWithId: function(id, event) {
+      if (!this.flowEventsById_.hasOwnProperty(id)) {
+        this.flowEventsById_[id] = new Array();
+      }
+      this.flowEventsById_[id].push(event);
+    },
+
+    getFlowEventsWithId: function(id) {
+      if (!this.flowEventsById_.hasOwnProperty(id))
+        return [];
+      return this.flowEventsById_[id];
+    }
+  };
+
+  return {
+    ModelIndices: ModelIndices
+  };
+});
+</script>
+
diff --git a/trace-viewer/trace_viewer/model/model_indices_test.html b/trace-viewer/trace_viewer/model/model_indices_test.html
new file mode 100644
index 0000000..4fc7fba
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/model_indices_test.html
@@ -0,0 +1,45 @@
+<!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="import" href="/core/test_utils.html">
+<link rel="import" href="/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  var newFlowEventEx = tr.c.test_utils.newFlowEventEx;
+  var newModel = tr.c.test_utils.newModel;
+
+  test('getCorrectModelIndices', function() {
+    var m = newModel(function(m) {
+      m.f1 = newFlowEventEx({
+        'title': 'test1',
+        start: 0,
+        end: 10,
+        id: '0x100'
+      });
+
+      m.f2 = newFlowEventEx({
+        'title': 'test2',
+        start: 0,
+        end: 10,
+        id: '0x100'
+      });
+
+      m.flowEvents.push(m.f1);
+      m.flowEvents.push(m.f2);
+    });
+
+    assert.isDefined(m.modelIndices);
+    var modelIndices = m.modelIndices;
+    assert.equal(modelIndices.getFlowEventsWithId('0x100').length, 2);
+    assert.equal(modelIndices.getFlowEventsWithId('0x100')[0].id, '0x100');
+    assert.equal(modelIndices.getFlowEventsWithId('0x101').length, 0);
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/trace_model_settings.html b/trace-viewer/trace_viewer/model/model_settings.html
similarity index 91%
rename from trace-viewer/trace_viewer/core/trace_model/trace_model_settings.html
rename to trace-viewer/trace_viewer/model/model_settings.html
index 0c04b73..cf6b63b 100644
--- a/trace-viewer/trace_viewer/core/trace_model/trace_model_settings.html
+++ b/trace-viewer/trace_viewer/model/model_settings.html
@@ -9,8 +9,8 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c', function() {
-  var Settings = tv.b.Settings;
+tr.exportTo('tr.model', function() {
+  var Settings = tr.b.Settings;
 
   /**
    * A way to persist settings specific to parts of a trace model.
@@ -22,12 +22,12 @@
    *
    * This system works on a notion of an object key: for an object's key, it
    * considers all the other keys in the model. If it is unique, then the key is
-   * persisted to tv.b.Settings. However, if it is not unique, then the
+   * persisted to tr.b.Settings. However, if it is not unique, then the
    * setting is stored on the object itself. Thus, objects with unique keys will
    * be persisted across page reloads, whereas objects with nonunique keys will
    * not.
    */
-  function TraceModelSettings(model) {
+  function ModelSettings(model) {
     this.model = model;
     this.objectsByKey_ = [];
     this.nonuniqueKeys_ = [];
@@ -36,7 +36,7 @@
     this.ephemeralSettingsByGUID_ = {};
   }
 
-  TraceModelSettings.prototype = {
+  ModelSettings.prototype = {
     buildObjectsByKeyMap_: function() {
       var objects = [];
       this.model.iterateAllPersistableObjects(function(o) {
@@ -58,7 +58,7 @@
       }
 
       var nonuniqueKeys = {};
-      tv.b.dictionaryKeys(objectsByKey).forEach(function(objectKey) {
+      tr.b.dictionaryKeys(objectsByKey).forEach(function(objectKey) {
         if (objectsByKey[objectKey] !== NONUNIQUE_KEY)
           return;
         delete objectsByKey[objectKey];
@@ -72,7 +72,7 @@
     removeNonuniqueKeysFromSettings_: function() {
       var settings = Settings.get('trace_model_settings', {});
       var settingsChanged = false;
-      tv.b.dictionaryKeys(settings).forEach(function(objectKey) {
+      tr.b.dictionaryKeys(settings).forEach(function(objectKey) {
         if (!this.nonuniqueKeys[objectKey])
           return;
         settingsChanged = true;
@@ -134,7 +134,7 @@
   };
 
   return {
-    TraceModelSettings: TraceModelSettings
+    ModelSettings: ModelSettings
   };
 });
 </script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/trace_model_settings_test.html b/trace-viewer/trace_viewer/model/model_settings_test.html
similarity index 76%
rename from trace-viewer/trace_viewer/core/trace_model/trace_model_settings_test.html
rename to trace-viewer/trace_viewer/model/model_settings_test.html
index 3a9ad96..5029899 100644
--- a/trace-viewer/trace_viewer/core/trace_model/trace_model_settings_test.html
+++ b/trace-viewer/trace_viewer/model/model_settings_test.html
@@ -5,53 +5,53 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/trace_model/trace_model_settings.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/model_settings.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('process_name_uniqueness_0', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isFalse(settings.hasUniqueSettingKey(p1));
   });
 
   test('process_name_uniqueness_1', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     p1.name = 'Browser';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.hasUniqueSettingKey(p1));
   });
 
   test('process_name_uniqueness_2', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var p2 = model.getOrCreateProcess(2);
     p1.name = 'Renderer';
     p2.name = 'Renderer';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isFalse(settings.hasUniqueSettingKey(p1));
     assert.isFalse(settings.hasUniqueSettingKey(p2));
   });
 
   test('process_name_uniqueness_3', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var p2 = model.getOrCreateProcess(2);
     p1.name = 'Renderer';
     p1.labels.push('Google Search');
     p2.name = 'Renderer';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.hasUniqueSettingKey(p1));
     assert.isTrue(settings.hasUniqueSettingKey(p2));
   });
 
   test('thread_name_uniqueness_0', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var p2 = model.getOrCreateProcess(2);
     var t1 = p1.getOrCreateThread(1);
@@ -60,13 +60,13 @@
     p2.name = 'Renderer';
     t1.name = 'Main';
     t2.name = 'Main';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.hasUniqueSettingKey(t1));
     assert.isTrue(settings.hasUniqueSettingKey(t2));
   });
 
   test('thread_name_uniqueness_1', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var p2 = model.getOrCreateProcess(2);
     var t1 = p1.getOrCreateThread(1);
@@ -75,47 +75,47 @@
     p2.name = 'Renderer';
     t1.name = 'Main';
     t2.name = 'Main';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isFalse(settings.hasUniqueSettingKey(t1));
     assert.isFalse(settings.hasUniqueSettingKey(t2));
   });
 
   test('process_persistence_when_not_unique', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.getSettingFor(p1, 'true_by_default', true));
 
     settings.setSettingFor(p1, 'true_by_default', false);
     assert.isFalse(settings.getSettingFor(p1, 'true_by_default', true));
 
     // Now, clobber the model, and verify that it didn't persist.
-    model = new tv.c.TraceModel();
+    model = new tr.Model();
     p1 = model.getOrCreateProcess(1);
-    settings = new tv.c.TraceModelSettings(model);
+    settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.getSettingFor(p1, 'true_by_default', true));
   });
 
   test('process_persistence_when_not_unique_with_name', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     p1.name = 'Browser';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.getSettingFor(p1, 'true_by_default', true));
 
     settings.setSettingFor(p1, 'true_by_default', false);
     assert.isFalse(settings.getSettingFor(p1, 'true_by_default', true));
 
     // Now, clobber the model, and verify that it persisted.
-    model = new tv.c.TraceModel();
+    model = new tr.Model();
     p1 = model.getOrCreateProcess(1);
     p1.name = 'Browser';
-    settings = new tv.c.TraceModelSettings(model);
+    settings = new tr.model.ModelSettings(model);
     assert.isFalse(settings.getSettingFor(p1, 'true_by_default', true));
   });
 
   test('thread_persistence_when_not_unique', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var p2 = model.getOrCreateProcess(2);
     var t1 = p1.getOrCreateThread(1);
@@ -124,14 +124,14 @@
     p2.name = 'Renderer';
     t1.name = 'Main';
     t2.name = 'Main';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.getSettingFor(t1, 'true_by_default', true));
 
     settings.setSettingFor(t1, 'true_by_default', false);
     assert.isFalse(settings.getSettingFor(t1, 'true_by_default', true));
 
     // Now, clobber the model, and verify that it persisted.
-    model = new tv.c.TraceModel();
+    model = new tr.Model();
     p1 = model.getOrCreateProcess(1);
     p2 = model.getOrCreateProcess(2);
     t1 = p1.getOrCreateThread(1);
@@ -140,12 +140,12 @@
     p2.name = 'Renderer';
     t1.name = 'Main';
     t2.name = 'Main';
-    settings = new tv.c.TraceModelSettings(model);
+    settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.getSettingFor(t1, 'true_by_default', true));
   });
 
   test('thread_persistence_when_unique', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var p2 = model.getOrCreateProcess(2);
     var t1 = p1.getOrCreateThread(1);
@@ -154,14 +154,14 @@
     p2.name = 'Renderer';
     t1.name = 'Main';
     t2.name = 'Main';
-    var settings = new tv.c.TraceModelSettings(model);
+    var settings = new tr.model.ModelSettings(model);
     assert.isTrue(settings.getSettingFor(t1, 'true_by_default', true));
 
     settings.setSettingFor(t1, 'true_by_default', false);
     assert.isFalse(settings.getSettingFor(t1, 'true_by_default', true));
 
     // Now, clobber the model, and verify that it persisted.
-    model = new tv.c.TraceModel();
+    model = new tr.Model();
     p1 = model.getOrCreateProcess(1);
     p2 = model.getOrCreateProcess(2);
     t1 = p1.getOrCreateThread(1);
@@ -170,7 +170,7 @@
     p2.name = 'Renderer';
     t1.name = 'Main';
     t2.name = 'Main';
-    settings = new tv.c.TraceModelSettings(model);
+    settings = new tr.model.ModelSettings(model);
     assert.isFalse(settings.getSettingFor(t1, 'true_by_default', true));
   });
 });
diff --git a/trace-viewer/trace_viewer/core/trace_model/trace_model_test.html b/trace-viewer/trace_viewer/model/model_test.html
similarity index 69%
rename from trace-viewer/trace_viewer/core/trace_model/trace_model_test.html
rename to trace-viewer/trace_viewer/model/model_test.html
index 1c9e6c4..e9d9dfc 100644
--- a/trace-viewer/trace_viewer/core/trace_model/trace_model_test.html
+++ b/trace-viewer/trace_viewer/model/model_test.html
@@ -6,33 +6,32 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/annotation.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
 <link rel="import" href="/extras/full_config.html">
+<link rel="import" href="/model/annotation.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ThreadSlice = tv.c.trace_model.ThreadSlice;
-  var TraceModel = tv.c.TraceModel;
-  var TitleOrCategoryFilter = tv.c.TitleOrCategoryFilter;
-  var Frame = tv.c.trace_model.Frame;
+tr.b.unittest.testSuite(function() {
+  var ThreadSlice = tr.model.ThreadSlice;
+  var TitleOrCategoryFilter = tr.c.TitleOrCategoryFilter;
+  var Frame = tr.model.Frame;
 
-  var createTraceModelWithOneOfEverything = function() {
-    var m = new TraceModel();
+  var createModelWithOneOfEverything = function() {
+    var m = new tr.Model();
     var cpu = m.kernel.getOrCreateCpu(1);
-    cpu.slices.push(tv.c.test_utils.newSlice(1, 3));
+    cpu.slices.push(tr.c.test_utils.newSlice(1, 3));
 
     var p = m.getOrCreateProcess(1);
     var t = p.getOrCreateThread(1);
     var slice = new ThreadSlice('', 'a', 0, 1, {}, 4);
     t.sliceGroup.pushSlice(slice);
-    t.asyncSliceGroup.push(tv.c.test_utils.newAsyncSlice(0, 1, t, t));
+    t.asyncSliceGroup.push(tr.c.test_utils.newAsyncSlice(0, 1, t, t));
 
     var c = p.getOrCreateCounter('', 'ProcessCounter');
-    var aSeries = new tv.c.trace_model.CounterSeries('a', 0);
-    var bSeries = new tv.c.trace_model.CounterSeries('b', 0);
+    var aSeries = new tr.model.CounterSeries('a', 0);
+    var bSeries = new tr.model.CounterSeries('b', 0);
     c.addSeries(aSeries);
     c.addSeries(bSeries);
 
@@ -47,8 +46,8 @@
     bSeries.addCounterSample(3, 16);
 
     var c1 = cpu.getOrCreateCounter('', 'CpuCounter');
-    var aSeries = new tv.c.trace_model.CounterSeries('a', 0);
-    var bSeries = new tv.c.trace_model.CounterSeries('b', 0);
+    var aSeries = new tr.model.CounterSeries('a', 0);
+    var bSeries = new tr.model.CounterSeries('b', 0);
     c1.addSeries(aSeries);
     c1.addSeries(bSeries);
 
@@ -65,8 +64,8 @@
     var frame1 = new Frame([slice], [{thread: t, start: 1, end: 5}]);
     p.frames.push.apply(p.frames, frame1);
 
-    var gd = new tv.c.trace_model.GlobalMemoryDump(m, 2);
-    var pd = new tv.c.trace_model.ProcessMemoryDump(gd, p, 2);
+    var gd = new tr.model.GlobalMemoryDump(m, 2);
+    var pd = new tr.model.ProcessMemoryDump(gd, p, 2);
     gd.processMemoryDumps[1] = pd;
     m.globalMemoryDumps.push(gd);
     p.memoryDumps.push(pd);
@@ -76,23 +75,23 @@
     return m;
   };
 
-  test('traceModelBounds_EmptyTraceModel', function() {
-    var m = new TraceModel();
+  test('modelBounds_EmptyModel', function() {
+    var m = new tr.Model();
     m.updateBounds();
     assert.isUndefined(m.bounds.min);
     assert.isUndefined(m.bounds.max);
   });
 
-  test('traceModelBounds_OneEmptyThread', function() {
-    var m = new TraceModel();
+  test('modelBounds_OneEmptyThread', function() {
+    var m = new tr.Model();
     var t = m.getOrCreateProcess(1).getOrCreateThread(1);
     m.updateBounds();
     assert.isUndefined(m.bounds.min);
     assert.isUndefined(m.bounds.max);
   });
 
-  test('traceModelBounds_OneThread', function() {
-    var m = new TraceModel();
+  test('modelBounds_OneThread', function() {
+    var m = new tr.Model();
     var t = m.getOrCreateProcess(1).getOrCreateThread(1);
     t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
     m.updateBounds();
@@ -100,8 +99,8 @@
     assert.equal(m.bounds.max, 4);
   });
 
-  test('traceModelBounds_OneThreadAndOneEmptyThread', function() {
-    var m = new TraceModel();
+  test('modelBounds_OneThreadAndOneEmptyThread', function() {
+    var m = new tr.Model();
     var t1 = m.getOrCreateProcess(1).getOrCreateThread(1);
     t1.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
     var t2 = m.getOrCreateProcess(1).getOrCreateThread(1);
@@ -110,19 +109,19 @@
     assert.equal(m.bounds.max, 4);
   });
 
-  test('traceModelBounds_OneCpu', function() {
-    var m = new TraceModel();
+  test('modelBounds_OneCpu', function() {
+    var m = new tr.Model();
     var cpu = m.kernel.getOrCreateCpu(1);
-    cpu.slices.push(tv.c.test_utils.newSlice(1, 3));
+    cpu.slices.push(tr.c.test_utils.newSlice(1, 3));
     m.updateBounds();
     assert.equal(m.bounds.min, 1);
     assert.equal(m.bounds.max, 4);
   });
 
-  test('traceModelBounds_OneCpuOneThread', function() {
-    var m = new TraceModel();
+  test('modelBounds_OneCpuOneThread', function() {
+    var m = new tr.Model();
     var cpu = m.kernel.getOrCreateCpu(1);
-    cpu.slices.push(tv.c.test_utils.newSlice(1, 3));
+    cpu.slices.push(tr.c.test_utils.newSlice(1, 3));
 
     var t = m.getOrCreateProcess(1).getOrCreateThread(1);
     t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 4));
@@ -132,37 +131,38 @@
     assert.equal(m.bounds.max, 5);
   });
 
-  test('traceModelBounds_GlobalMemoryDumps', function() {
-    var m = new TraceModel();
-    m.globalMemoryDumps.push(new tv.c.trace_model.GlobalMemoryDump(m, 1));
-    m.globalMemoryDumps.push(new tv.c.trace_model.GlobalMemoryDump(m, 3));
-    m.globalMemoryDumps.push(new tv.c.trace_model.GlobalMemoryDump(m, 5));
+  test('modelBounds_GlobalMemoryDumps', function() {
+    var m = new tr.Model();
+    m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 1));
+    m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 3));
+    m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 5));
 
     m.updateBounds();
     assert.equal(m.bounds.min, 1);
     assert.equal(m.bounds.max, 5);
   });
 
-  test('traceModelBounds_ProcessMemoryDumps', function() {
-    var m = new TraceModel();
+  test('modelBounds_ProcessMemoryDumps', function() {
+    var m = new tr.Model();
     var p = m.getOrCreateProcess(1);
-    var gd = new tv.c.trace_model.GlobalMemoryDump(m, -1);
-    p.memoryDumps.push(new tv.c.trace_model.ProcessMemoryDump(gd, m, 1));
-    p.memoryDumps.push(new tv.c.trace_model.ProcessMemoryDump(gd, m, 3));
-    p.memoryDumps.push(new tv.c.trace_model.ProcessMemoryDump(gd, m, 5));
+    var gd = new tr.model.GlobalMemoryDump(m, -1);
+    p.memoryDumps.push(new tr.model.ProcessMemoryDump(gd, m, 1));
+    p.memoryDumps.push(new tr.model.ProcessMemoryDump(gd, m, 3));
+    p.memoryDumps.push(new tr.model.ProcessMemoryDump(gd, m, 5));
 
     m.updateBounds();
     assert.equal(m.bounds.min, 1);
     assert.equal(m.bounds.max, 5);
   });
 
-  test('traceModelCanImportEmpty', function() {
+  test('modelCanImportEmpty', function() {
     var m;
-    m = new TraceModel([]);
-    m = new TraceModel('');
+    m = new tr.Model([]);
+    assert.isDefined(m.modelIndices);
+    m = new tr.Model('');
   });
 
-  test('traceModelCanImportSubtraces', function() {
+  test('modelCanImportSubtraces', function() {
     var systraceLines = [
       'SurfaceFlinger-2  [001] ...1 1000.0: 0: B|1|taskA',
       'SurfaceFlinger-2  [001] ...1 2000.0: 0: E',
@@ -181,9 +181,9 @@
       systemTraceEvents: systraceLines.join('\n')
     });
 
-    var m = new TraceModel();
+    var m = new tr.Model();
     m.importTraces([combined]);
-    assert.equal(tv.b.dictionaryValues(m.processes).length, 1);
+    assert.equal(tr.b.dictionaryValues(m.processes).length, 1);
 
     var p1 = m.processes[1];
     assert.isDefined(p1);
@@ -200,12 +200,12 @@
     assert.equal(t3.sliceGroup.slices[0].title, 'taskB');
   });
 
-  test('traceModelCanImportCompressedSingleSubtrace', function() {
+  test('modelCanImportCompressedSingleSubtrace', function() {
     var compressedTrace = atob('H4sIACKfFVUC/wsuLUpLTE51y8nMS08t0jVSUIg2MDCMV' +
         'dDT0zNUMDQwMNAzsFIAIqcaw5qSxOJsR65gfDqMEDpcATiC61ZbAAAA');
-    var m = new TraceModel();
+    var m = new tr.Model();
     m.importTraces([compressedTrace]);
-    assert.equal(1, tv.b.dictionaryValues(m.processes).length);
+    assert.equal(1, tr.b.dictionaryValues(m.processes).length);
 
     var p1 = m.processes[1];
     assert.isDefined(p1);
@@ -217,7 +217,7 @@
     assert.equal('taskA', t2.sliceGroup.slices[0].title);
   });
 
-  test('traceModelCanImportSubtracesRecursively', function() {
+  test('modelCanImportSubtracesRecursively', function() {
     var systraceLines = [
       'SurfaceFlinger-2  [001] ...1 1000.0: 0: B|1|taskA',
       'SurfaceFlinger-2  [001] ...1 2000.0: 0: E',
@@ -244,9 +244,9 @@
       systemTraceEvents: innerTrace
     });
 
-    var m = new TraceModel();
+    var m = new tr.Model();
     m.importTraces([outerTrace]);
-    assert.equal(tv.b.dictionaryValues(m.processes).length, 1);
+    assert.equal(tr.b.dictionaryValues(m.processes).length, 1);
 
     var p1 = m.processes[1];
     assert.isDefined(p1);
@@ -263,27 +263,27 @@
     assert.equal(t3.sliceGroup.slices[0].title, 'taskB');
   });
 
-  test('traceModelWithImportFailure', function() {
+  test('modelWithImportFailure', function() {
     var malformed = '{traceEvents: [{garbage';
-    var m = new TraceModel();
+    var m = new tr.Model();
     assert.throw(function() {
       m.importTraces([malformed]);
     });
   });
 
   test('TitleOrCategoryFilter', function() {
-    var s0 = tv.c.test_utils.newSlice(1, 3);
+    var s0 = tr.c.test_utils.newSlice(1, 3);
     assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s0));
     assert.isFalse(new TitleOrCategoryFilter('x').matchSlice(s0));
 
-    var s1 = tv.c.test_utils.newSliceNamed('ba', 1, 3);
+    var s1 = tr.c.test_utils.newSliceNamed('ba', 1, 3);
     assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s1));
     assert.isTrue(new TitleOrCategoryFilter('ba').matchSlice(s1));
     assert.isFalse(new TitleOrCategoryFilter('x').matchSlice(s1));
   });
 
-  test('traceModel_findAllThreadsNamed', function() {
-    var m = new TraceModel();
+  test('model_findAllThreadsNamed', function() {
+    var m = new tr.Model();
     var t = m.getOrCreateProcess(1).getOrCreateThread(1);
     t.name = 'CrBrowserMain';
 
@@ -294,8 +294,8 @@
     assert.equal(f.length, 0);
   });
 
-  test('traceModel_updateCategories', function() {
-    var m = new TraceModel();
+  test('model_updateCategories', function() {
+    var m = new tr.Model();
     var t = m.getOrCreateProcess(1).getOrCreateThread(1);
     t.sliceGroup.pushSlice(new ThreadSlice('categoryA', 'a', 0, 1, {}, 3));
     t.sliceGroup.pushSlice(new ThreadSlice('categoryA', 'a', 0, 1, {}, 3));
@@ -306,18 +306,18 @@
     assert.deepEqual(['categoryA', 'categoryB'], m.categories);
   });
 
-  test('traceModel_iterateAllEvents', function() {
-    var m = createTraceModelWithOneOfEverything();
+  test('model_iterateAllEvents', function() {
+    var m = createModelWithOneOfEverything();
     var wasCalled = false;
     m.iterateAllEvents(function(event) {
-      assert.isTrue(event instanceof tv.c.trace_model.Event);
+      assert.isTrue(event instanceof tr.model.Event);
       wasCalled = true;
     });
     assert.isTrue(wasCalled);
   });
 
   test('customizeCallback', function() {
-    var m = new tv.c.TraceModel();
+    var m = new tr.Model();
     m.importTraces([], false, false, function() {
       var browserProcess = m.getOrCreateProcess(1);
       var browserMain = browserProcess.getOrCreateThread(2);
@@ -333,8 +333,8 @@
     assert.equal(t2.sliceGroup.topLevelSlices.length, 2);
   });
 
-  test('traceModel_sortsSamples', function() {
-    var m = new tv.c.TraceModel();
+  test('model_sortsSamples', function() {
+    var m = new tr.Model();
     // The 184, 0 and 185 are the tick-times
     // and irrespective of the order
     // in which the lines appear in the trace,
@@ -347,32 +347,32 @@
     assert.equal(m.samples[2].start, 0.185);
   });
 
-  test('traceModel_sortsGlobalMemoryDumps', function() {
-    var m = new tv.c.TraceModel();
+  test('model_sortsGlobalMemoryDumps', function() {
+    var m = new tr.Model();
     m.importTraces([], true /* shiftWorldToZero */, false, function() {
-      m.globalMemoryDumps.push(new tv.c.trace_model.GlobalMemoryDump(m, 1));
-      m.globalMemoryDumps.push(new tv.c.trace_model.GlobalMemoryDump(m, 5));
-      m.globalMemoryDumps.push(new tv.c.trace_model.GlobalMemoryDump(m, 3));
+      m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 1));
+      m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 5));
+      m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 3));
     });
     assert.equal(m.globalMemoryDumps[0].start, 0);
     assert.equal(m.globalMemoryDumps[1].start, 2);
     assert.equal(m.globalMemoryDumps[2].start, 4);
   });
 
-  test('traceModel_finalizesProcessMemoryDumps', function() {
-    var m = new tv.c.TraceModel();
+  test('model_finalizesProcessMemoryDumps', function() {
+    var m = new tr.Model();
     var p = m.getOrCreateProcess(1);
     m.importTraces([], true /* shiftWorldToZero */, false, function() {
-      var g = new tv.c.trace_model.GlobalMemoryDump(m, -1);
+      var g = new tr.model.GlobalMemoryDump(m, -1);
       m.globalMemoryDumps.push(g);
 
-      var pmd1 = new tv.c.trace_model.ProcessMemoryDump(g, p, 1);
+      var pmd1 = new tr.model.ProcessMemoryDump(g, p, 1);
       p.memoryDumps.push(pmd1);
 
-      var pmd2 = new tv.c.trace_model.ProcessMemoryDump(g, p, 5);
+      var pmd2 = new tr.model.ProcessMemoryDump(g, p, 5);
       p.memoryDumps.push(pmd2);
 
-      var pmd3 = new tv.c.trace_model.ProcessMemoryDump(g, p, 3);
+      var pmd3 = new tr.model.ProcessMemoryDump(g, p, 3);
       p.memoryDumps.push(pmd3);
       pmd3.vmRegions = [];
     });
@@ -390,10 +390,10 @@
         p.memoryDumps[2].mostRecentVmRegions);
   });
 
-  test('traceModel_annotationAddRemove', function() {
-    var m = new tv.c.TraceModel();
-    var a1 = new tv.c.trace_model.Annotation();
-    var a2 = new tv.c.trace_model.Annotation();
+  test('model_annotationAddRemove', function() {
+    var m = new tr.Model();
+    var a1 = new tr.model.Annotation();
+    var a2 = new tr.model.Annotation();
 
     assert.equal(m.getAllAnnotations().length, 0);
     m.addAnnotation(a1);
diff --git a/trace-viewer/trace_viewer/core/trace_model/multi_async_slice_sub_view_test.html b/trace-viewer/trace_viewer/model/multi_async_slice_sub_view_test.html
similarity index 76%
rename from trace-viewer/trace_viewer/core/trace_model/multi_async_slice_sub_view_test.html
rename to trace-viewer/trace_viewer/model/multi_async_slice_sub_view_test.html
index a2d3d4c..a36a700 100644
--- a/trace-viewer/trace_viewer/core/trace_model/multi_async_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/model/multi_async_slice_sub_view_test.html
@@ -8,16 +8,16 @@
 <link rel="import" href="/core/analysis/multi_async_slice_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newAsyncSliceEx = tv.c.test_utils.newAsyncSliceEx;
+tr.b.unittest.testSuite(function() {
+  var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx;
 
   test('instantiate', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.asyncSliceGroup.push(newAsyncSliceEx({
@@ -35,11 +35,11 @@
       endThread: t1
     }));
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(t1.asyncSliceGroup.slices[0]);
     selection.push(t1.asyncSliceGroup.slices[1]);
 
-    var viewEl = document.createElement('tv-c-a-multi-async-slice-sub-view');
+    var viewEl = document.createElement('tr-c-a-multi-async-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/core/trace_model/object_collection.html b/trace-viewer/trace_viewer/model/object_collection.html
similarity index 89%
rename from trace-viewer/trace_viewer/core/trace_model/object_collection.html
rename to trace-viewer/trace_viewer/model/object_collection.html
index 4d20a50..686e7c7 100644
--- a/trace-viewer/trace_viewer/core/trace_model/object_collection.html
+++ b/trace-viewer/trace_viewer/model/object_collection.html
@@ -5,9 +5,9 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/event_container.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
-<link rel="import" href="/core/trace_model/time_to_object_instance_map.html">
+<link rel="import" href="/model/event_container.html">
+<link rel="import" href="/model/object_instance.html">
+<link rel="import" href="/model/time_to_object_instance_map.html">
 <link rel="import" href="/base/utils.html">
 <link rel="import" href="/base/range.html">
 <link rel="import" href="/base/sorted_array_utils.html">
@@ -18,9 +18,9 @@
 /**
  * @fileoverview Provides the ObjectCollection class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var ObjectInstance = tv.c.trace_model.ObjectInstance;
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.model', function() {
+  var ObjectInstance = tr.model.ObjectInstance;
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * A collection of object instances and their snapshots, accessible by id and
@@ -29,16 +29,16 @@
    * @constructor
    */
   function ObjectCollection(parent) {
-    tv.c.trace_model.EventContainer.call(this);
+    tr.model.EventContainer.call(this);
     this.parent = parent;
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
     this.instanceMapsById_ = {}; // id -> TimeToObjectInstanceMap
     this.instancesByTypeName_ = {};
     this.createObjectInstance_ = this.createObjectInstance_.bind(this);
   }
 
   ObjectCollection.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+    __proto__: tr.model.EventContainer.prototype,
 
     iterateAllChildEventContainers: function(callback, opt_this) {
     },
@@ -59,7 +59,7 @@
 
     createObjectInstance_: function(
         parent, id, category, name, creationTs, opt_baseTypeName) {
-      var constructor = tv.c.trace_model.ObjectInstance.getConstructor(
+      var constructor = tr.model.ObjectInstance.getConstructor(
           category, name);
       var instance = new constructor(
           parent, id, category, name, creationTs, opt_baseTypeName);
@@ -77,7 +77,7 @@
       var instanceMap = this.instanceMapsById_[id];
       if (instanceMap)
         return instanceMap;
-      instanceMap = new tv.c.trace_model.TimeToObjectInstanceMap(
+      instanceMap = new tr.model.TimeToObjectInstanceMap(
           this.createObjectInstance_, this.parent, id);
       this.instanceMapsById_[id] = instanceMap;
       return instanceMap;
@@ -136,7 +136,7 @@
     },
 
     autoDeleteObjects: function(maxTimestamp) {
-      tv.b.iterItems(this.instanceMapsById_, function(id, i2imap) {
+      tr.b.iterItems(this.instanceMapsById_, function(id, i2imap) {
         var lastInstance = i2imap.lastInstance;
         if (lastInstance.deletionTs != Number.MAX_VALUE)
           return;
@@ -164,7 +164,7 @@
 
     iterObjectInstances: function(iter, opt_this) {
       opt_this = opt_this || this;
-      tv.b.iterItems(this.instanceMapsById_, function(id, i2imap) {
+      tr.b.iterItems(this.instanceMapsById_, function(id, i2imap) {
         i2imap.instances.forEach(iter, opt_this);
       });
     },
diff --git a/trace-viewer/trace_viewer/core/trace_model/object_collection_test.html b/trace-viewer/trace_viewer/model/object_collection_test.html
similarity index 80%
rename from trace-viewer/trace_viewer/core/trace_model/object_collection_test.html
rename to trace-viewer/trace_viewer/model/object_collection_test.html
index 51ce02f..f41854b 100644
--- a/trace-viewer/trace_viewer/core/trace_model/object_collection_test.html
+++ b/trace-viewer/trace_viewer/model/object_collection_test.html
@@ -6,52 +6,52 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/object_collection.html">
+<link rel="import" href="/model/object_collection.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() { // @suppress longLineCheck
+tr.b.unittest.testSuite(function() { // @suppress longLineCheck
   var TestObjectInstance = function(parent, id, category, name, creationTs) {
-    tv.c.trace_model.ObjectInstance.call(
+    tr.model.ObjectInstance.call(
         this, parent, id, category, name, creationTs);
   };
 
   TestObjectInstance.prototype = {
-    __proto__: tv.c.trace_model.ObjectInstance.prototype
+    __proto__: tr.model.ObjectInstance.prototype
   };
 
   test('objectInstanceSubtype', function() {
     // Register that TestObjects are bound to TestObjectInstance.
-    tv.c.trace_model.ObjectInstance.register(
+    tr.model.ObjectInstance.register(
         TestObjectInstance,
         {typeName: 'TestObject'});
 
     try {
-      var collection = new tv.c.trace_model.ObjectCollection({ });
+      var collection = new tr.model.ObjectCollection({ });
       collection.idWasCreated(
-          '0x1000', 'tv.e.cc', 'Frame', 10);
+          '0x1000', 'tr.e.cc', 'Frame', 10);
       collection.idWasDeleted(
-          '0x1000', 'tv.e.cc', 'Frame', 15);
+          '0x1000', 'tr.e.cc', 'Frame', 15);
       collection.idWasCreated(
           '0x1000', 'skia', 'TestObject', 20);
       collection.idWasDeleted(
           '0x1000', 'skia', 'TestObject', 25);
 
       var testFrame = collection.getObjectInstanceAt('0x1000', 10);
-      assert.instanceOf(testFrame, tv.c.trace_model.ObjectInstance);
+      assert.instanceOf(testFrame, tr.model.ObjectInstance);
       assert.notInstanceOf(testFrame, TestObjectInstance);
 
       var testObject = collection.getObjectInstanceAt('0x1000', 20);
-      assert.instanceOf(testObject, tv.c.trace_model.ObjectInstance);
+      assert.instanceOf(testObject, tr.model.ObjectInstance);
       assert.instanceOf(testObject, TestObjectInstance);
     } finally {
-      tv.c.trace_model.ObjectInstance.unregister(TestObjectInstance);
+      tr.model.ObjectInstance.unregister(TestObjectInstance);
     }
   });
 
   test('twoSnapshots', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     collection.idWasCreated(
         '0x1000', 'cat', 'Frame', 10);
     collection.addSnapshot(
@@ -82,25 +82,25 @@
   });
 
   test('twoObjectsSharingOneID', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     collection.idWasCreated(
-        '0x1000', 'tv.e.cc', 'Frame', 10);
+        '0x1000', 'tr.e.cc', 'Frame', 10);
     collection.idWasDeleted(
-        '0x1000', 'tv.e.cc', 'Frame', 15);
+        '0x1000', 'tr.e.cc', 'Frame', 15);
     collection.idWasCreated(
         '0x1000', 'skia', 'Picture', 20);
     collection.idWasDeleted(
         '0x1000', 'skia', 'Picture', 25);
 
     var frame = collection.getObjectInstanceAt('0x1000', 10);
-    assert.equal(frame.category, 'tv.e.cc');
+    assert.equal(frame.category, 'tr.e.cc');
     assert.equal(frame.name, 'Frame');
 
     var picture = collection.getObjectInstanceAt('0x1000', 20);
     assert.equal(picture.category, 'skia');
     assert.equal(picture.name, 'Picture');
 
-    var typeNames = tv.b.dictionaryKeys(collection.getAllInstancesByTypeName());
+    var typeNames = tr.b.dictionaryKeys(collection.getAllInstancesByTypeName());
     typeNames.sort();
     assert.deepEqual(
         ['Frame', 'Picture'],
@@ -114,7 +114,7 @@
   });
 
   test('createSnapDelete', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     collection.idWasCreated(
         '0x1000', 'cat', 'Frame', 10);
     collection.addSnapshot(
@@ -133,7 +133,7 @@
   });
 
   test('boundsOnUndeletedObject', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     collection.idWasCreated(
         '0x1000', 'cat', 'Frame', 10);
     collection.addSnapshot(
@@ -145,7 +145,7 @@
   });
 
   test('snapshotWithCustomBaseTypeThenDelete', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     var s10 = collection.addSnapshot(
         '0x1000', 'cat', 'cc::PictureLayerImpl', 10, {}, 'cc::LayerImpl');
     collection.idWasDeleted(
@@ -158,7 +158,7 @@
   });
 
   test('newWithSnapshotThatChangesBaseType', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     var i10 = collection.idWasCreated(
         '0x1000', 'cat', 'cc::LayerImpl', 10);
     var s15 = collection.addSnapshot(
@@ -172,7 +172,7 @@
   });
 
   test('deleteThenSnapshotWithCustomBase', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     collection.idWasDeleted(
         '0x1000', 'cat', 'cc::LayerImpl', 10);
     var s15 = collection.addSnapshot(
@@ -184,7 +184,7 @@
   });
 
   test('autoDelete', function() {
-    var collection = new tv.c.trace_model.ObjectCollection({});
+    var collection = new tr.model.ObjectCollection({});
     collection.idWasCreated(
         '0x1000', 'cat', 'Frame', 10);
     collection.addSnapshot(
diff --git a/trace-viewer/trace_viewer/core/trace_model/object_instance.html b/trace-viewer/trace_viewer/model/object_instance.html
similarity index 87%
rename from trace-viewer/trace_viewer/core/trace_model/object_instance.html
rename to trace-viewer/trace_viewer/model/object_instance.html
index 4193cf0..56e0828 100644
--- a/trace-viewer/trace_viewer/core/trace_model/object_instance.html
+++ b/trace-viewer/trace_viewer/model/object_instance.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/base/extension_registry.html">
-<link rel="import" href="/core/trace_model/event.html">
-<link rel="import" href="/core/trace_model/object_snapshot.html">
+<link rel="import" href="/model/event.html">
+<link rel="import" href="/model/object_snapshot.html">
 <link rel="import" href="/base/range.html">
 <link rel="import" href="/base/sorted_array_utils.html">
 
@@ -17,8 +17,8 @@
 /**
  * @fileoverview Provides the ObjectSnapshot and ObjectHistory classes.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
+tr.exportTo('tr.model', function() {
+  var ObjectSnapshot = tr.model.ObjectSnapshot;
 
   /**
    * An object with a specific id, whose state has been snapshotted several
@@ -28,7 +28,7 @@
    */
   function ObjectInstance(
       parent, id, category, name, creationTs, opt_baseTypeName) {
-    tv.c.trace_model.Event.call(this);
+    tr.model.Event.call(this);
     this.parent = parent;
     this.id = id;
     this.category = category;
@@ -39,13 +39,13 @@
     this.deletionTs = Number.MAX_VALUE;
     this.deletionTsWasExplicit = false;
     this.colorId = 0;
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
     this.snapshots = [];
     this.hasImplicitSnapshots = false;
   }
 
   ObjectInstance.prototype = {
-    __proto__: tv.c.trace_model.Event.prototype,
+    __proto__: tr.model.Event.prototype,
 
     get typeName() {
       return this.name;
@@ -84,7 +84,7 @@
       }
 
       var snapshotConstructor =
-          tv.c.trace_model.ObjectSnapshot.getConstructor(
+          tr.model.ObjectSnapshot.getConstructor(
               this.category, this.name);
       var snapshot = new snapshotConstructor(this, ts, args);
       this.snapshots.push(snapshot);
@@ -130,7 +130,7 @@
         throw new Error('ts must be within lifetime of this instance');
 
       var snapshots = this.snapshots;
-      var i = tv.b.findIndexInSortedIntervals(
+      var i = tr.b.findIndexInSortedIntervals(
           snapshots,
           function(snapshot) { return snapshot.ts; },
           function(snapshot, i) {
@@ -175,20 +175,20 @@
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
     ObjectInstance,
     {
       name: 'objectInstance',
       pluralName: 'objectInstances',
-      singleViewElementName: 'tv-c-single-object-instance-sub-view',
-      multiViewElementName: 'tv-c-multi-object-sub-view'
+      singleViewElementName: 'tr-c-a-single-object-instance-sub-view',
+      multiViewElementName: 'tr-c-a-multi-object-sub-view'
     });
 
-  var options = new tv.b.ExtensionRegistryOptions(
-      tv.b.TYPE_BASED_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(
+      tr.b.TYPE_BASED_REGISTRY_MODE);
   options.mandatoryBaseClass = ObjectInstance;
   options.defaultConstructor = ObjectInstance;
-  tv.b.decorateExtensionRegistry(ObjectInstance, options);
+  tr.b.decorateExtensionRegistry(ObjectInstance, options);
 
   return {
     ObjectInstance: ObjectInstance
diff --git a/trace-viewer/trace_viewer/core/trace_model/object_instance_test.html b/trace-viewer/trace_viewer/model/object_instance_test.html
similarity index 83%
rename from trace-viewer/trace_viewer/core/trace_model/object_instance_test.html
rename to trace-viewer/trace_viewer/model/object_instance_test.html
index 5bb622e..db0e74a 100644
--- a/trace-viewer/trace_viewer/core/trace_model/object_instance_test.html
+++ b/trace-viewer/trace_viewer/model/object_instance_test.html
@@ -6,14 +6,14 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('getSnapshotAtWithImplicitCreation', function() {
-    var instance = new tv.c.trace_model.ObjectInstance(
+    var instance = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'n', 10);
     var s10 = instance.addSnapshot(10, 'a');
     instance.addSnapshot(40, 'b');
@@ -33,7 +33,7 @@
   });
 
   test('getSnapshotAtWithExplicitCreation', function() {
-    var instance = new tv.c.trace_model.ObjectInstance(
+    var instance = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'n', 10);
     instance.creationTsWasExplicit = true;
     instance.addSnapshot(10, 'a');
@@ -49,7 +49,7 @@
   });
 
   test('getSnapshotBeforeFirstSnapshot', function() {
-    var instance = new tv.c.trace_model.ObjectInstance(
+    var instance = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'n', 10);
     var s15 = instance.addSnapshot(15, 'a');
     instance.wasDeleted(40);
@@ -58,7 +58,7 @@
   });
 
   test('getSnapshotAfterLastSnapshot', function() {
-    var instance = new tv.c.trace_model.ObjectInstance(
+    var instance = new tr.model.ObjectInstance(
         {}, '0x1000', 'cat', 'n', 10);
     var s15 = instance.addSnapshot(15, 'a');
     instance.wasDeleted(40);
diff --git a/trace-viewer/trace_viewer/core/trace_model/object_snapshot.html b/trace-viewer/trace_viewer/model/object_snapshot.html
similarity index 78%
rename from trace-viewer/trace_viewer/core/trace_model/object_snapshot.html
rename to trace-viewer/trace_viewer/model/object_snapshot.html
index 8ed7433..15e4fe7 100644
--- a/trace-viewer/trace_viewer/core/trace_model/object_snapshot.html
+++ b/trace-viewer/trace_viewer/model/object_snapshot.html
@@ -6,13 +6,13 @@
 -->
 
 <link rel="import" href="/base/extension_registry.html">
-<link rel="import" href="/core/analysis/util.html">
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/base/units/util.html">
+<link rel="import" href="/model/event.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * A snapshot of an object instance, at a given moment in time.
    *
@@ -36,14 +36,14 @@
    * @constructor
    */
   function ObjectSnapshot(objectInstance, ts, args) {
-    tv.c.trace_model.Event.call(this);
+    tr.model.Event.call(this);
     this.objectInstance = objectInstance;
     this.ts = ts;
     this.args = args;
   }
 
   ObjectSnapshot.prototype = {
-    __proto__: tv.c.trace_model.Event.prototype,
+    __proto__: tr.model.Event.prototype,
 
     /**
      * See ObjectSnapshot constructor notes on object initialization.
@@ -65,24 +65,24 @@
       return 'Snapshot of ' +
              this.objectInstance.typeName + ' ' +
              this.objectInstance.id + ' @ ' +
-             tv.c.analysis.tsString(this.ts);
+             tr.b.units.tsString(this.ts);
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       ObjectSnapshot,
       {
         name: 'objectSnapshot',
         pluralName: 'objectSnapshots',
-        singleViewElementName: 'tv-c-single-object-snapshot-sub-view',
-        multiViewElementName: 'tv-c-multi-object-sub-view'
+        singleViewElementName: 'tr-c-a-single-object-snapshot-sub-view',
+        multiViewElementName: 'tr-c-a-multi-object-sub-view'
       });
 
-  var options = new tv.b.ExtensionRegistryOptions(
-      tv.b.TYPE_BASED_REGISTRY_MODE);
+  var options = new tr.b.ExtensionRegistryOptions(
+      tr.b.TYPE_BASED_REGISTRY_MODE);
   options.mandatoryBaseClass = ObjectSnapshot;
   options.defaultConstructor = ObjectSnapshot;
-  tv.b.decorateExtensionRegistry(ObjectSnapshot, options);
+  tr.b.decorateExtensionRegistry(ObjectSnapshot, options);
 
   return {
     ObjectSnapshot: ObjectSnapshot
diff --git a/trace-viewer/trace_viewer/model/object_snapshot_test.html b/trace-viewer/trace_viewer/model/object_snapshot_test.html
new file mode 100644
index 0000000..185aa4b
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/object_snapshot_test.html
@@ -0,0 +1,40 @@
+<!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="import" href="/model/object_instance.html">
+<link rel="import" href="/model/object_snapshot.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('snapshotTypeRegistry', function() {
+    function MySnapshot() {
+      tr.model.ObjectSnapshot.apply(this, arguments);
+      this.myFoo = this.args.foo;
+    }
+
+    MySnapshot.prototype = {
+      __proto__: tr.model.ObjectSnapshot.prototype
+    };
+
+    var instance = new tr.model.ObjectInstance(
+        {}, '0x1000', 'cat', 'MySnapshot', 10);
+    try {
+      tr.model.ObjectSnapshot.register(
+          MySnapshot,
+          {typeName: 'MySnapshot'});
+      var snapshot = instance.addSnapshot(15, {foo: 'bar'});
+      assert.instanceOf(snapshot, MySnapshot);
+      assert.equal(snapshot.myFoo, 'bar');
+    } finally {
+      tr.model.ObjectSnapshot.unregister(MySnapshot);
+    }
+  });
+});
+</script>
+
diff --git a/trace-viewer/trace_viewer/core/trace_model/process.html b/trace-viewer/trace_viewer/model/process.html
similarity index 81%
rename from trace-viewer/trace_viewer/core/trace_model/process.html
rename to trace-viewer/trace_viewer/model/process.html
index 6062883..1df58ad 100644
--- a/trace-viewer/trace_viewer/core/trace_model/process.html
+++ b/trace-viewer/trace_viewer/model/process.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/process_base.html">
-<link rel="import" href="/core/trace_model/process_memory_dump.html">
+<link rel="import" href="/model/process_base.html">
+<link rel="import" href="/model/process_memory_dump.html">
 
 <script>
 'use strict';
@@ -14,11 +14,11 @@
 /**
  * @fileoverview Provides the Process class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var ProcessBase = tv.c.trace_model.ProcessBase;
-  var ProcessInstantEvent = tv.c.trace_model.ProcessInstantEvent;
-  var Frame = tv.c.trace_model.Frame;
-  var ProcessMemoryDump = tv.c.trace_model.ProcessMemoryDump;
+tr.exportTo('tr.model', function() {
+  var ProcessBase = tr.model.ProcessBase;
+  var ProcessInstantEvent = tr.model.ProcessInstantEvent;
+  var Frame = tr.model.Frame;
+  var ProcessMemoryDump = tr.model.ProcessMemoryDump;
 
   /**
    * The Process represents a single userland process in the
@@ -30,7 +30,7 @@
       throw new Error('model must be provided');
     if (pid === undefined)
       throw new Error('pid must be provided');
-    tv.c.trace_model.ProcessBase.call(this, model);
+    tr.model.ProcessBase.call(this, model);
     this.pid = pid;
     this.name = undefined;
     this.labels = [];
@@ -43,17 +43,17 @@
    * Comparison between processes that orders by pid.
    */
   Process.compare = function(x, y) {
-    var tmp = tv.c.trace_model.ProcessBase.compare(x, y);
+    var tmp = tr.model.ProcessBase.compare(x, y);
     if (tmp)
       return tmp;
 
-    tmp = tv.b.comparePossiblyUndefinedValues(
+    tmp = tr.b.comparePossiblyUndefinedValues(
         x.name, y.name,
         function(x, y) { return x.localeCompare(y); });
     if (tmp)
       return tmp;
 
-    tmp = tv.b.compareArrays(x.labels, y.labels,
+    tmp = tr.b.compareArrays(x.labels, y.labels,
         function(x, y) { return x.localeCompare(y); });
     if (tmp)
       return tmp;
@@ -62,7 +62,7 @@
   };
 
   Process.prototype = {
-    __proto__: tv.c.trace_model.ProcessBase.prototype,
+    __proto__: tr.model.ProcessBase.prototype,
 
     get stableId() {
       return this.pid;
@@ -139,12 +139,12 @@
       for (var i = 0; i < this.memoryDumps.length; i++)
         this.memoryDumps[i].shiftTimestampsForward(amount);
 
-      tv.c.trace_model.ProcessBase.prototype
+      tr.model.ProcessBase.prototype
           .shiftTimestampsForward.apply(this, arguments);
     },
 
     updateBounds: function() {
-      tv.c.trace_model.ProcessBase.prototype.updateBounds.apply(this);
+      tr.model.ProcessBase.prototype.updateBounds.apply(this);
 
       for (var i = 0; i < this.frames.length; i++)
         this.frames[i].addBoundsToRange(this.bounds);
@@ -153,11 +153,11 @@
         this.memoryDumps[i].addBoundsToRange(this.bounds);
     },
 
-    finalizeMemoryDumps: function() {
+    sortMemoryDumps: function() {
       this.memoryDumps.sort(function(x, y) {
         return x.start - y.start;
       });
-      tv.c.trace_model.ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(
+      tr.model.ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(
           this.memoryDumps);
     }
   };
diff --git a/trace-viewer/trace_viewer/core/trace_model/process_base.html b/trace-viewer/trace_viewer/model/process_base.html
similarity index 87%
rename from trace-viewer/trace_viewer/core/trace_model/process_base.html
rename to trace-viewer/trace_viewer/model/process_base.html
index fa75141..c73c4d8 100644
--- a/trace-viewer/trace_viewer/core/trace_model/process_base.html
+++ b/trace-viewer/trace_viewer/model/process_base.html
@@ -5,13 +5,13 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/counter.html">
-<link rel="import" href="/core/trace_model/event_container.html">
-<link rel="import" href="/core/trace_model/object_collection.html">
-<link rel="import" href="/core/trace_model/thread.html">
-<link rel="import" href="/core/trace_model/trace_model_settings.html">
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/base/range.html">
+<link rel="import" href="/model/counter.html">
+<link rel="import" href="/model/event_container.html">
+<link rel="import" href="/model/object_collection.html">
+<link rel="import" href="/model/thread.html">
+<link rel="import" href="/model/model_settings.html">
 
 <script>
 'use strict';
@@ -19,28 +19,28 @@
 /**
  * @fileoverview Provides the ProcessBase class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
-  var Thread = tv.c.trace_model.Thread;
-  var Counter = tv.c.trace_model.Counter;
+  var Thread = tr.model.Thread;
+  var Counter = tr.model.Counter;
 
   /**
    * The ProcessBase is a partial base class, upon which Kernel
    * and Process are built.
    *
    * @constructor
-   * @extends {tv.c.trace_model.EventContainer}
+   * @extends {tr.model.EventContainer}
    */
   function ProcessBase(model) {
     if (!model)
       throw new Error('Must provide a model');
-    tv.c.trace_model.EventContainer.call(this, model);
-    this.guid_ = tv.b.GUID.allocate();
+    tr.model.EventContainer.call(this);
+    this.guid_ = tr.b.GUID.allocate();
     this.model = model;
     this.threads = {};
     this.counters = {};
-    this.objects = new tv.c.trace_model.ObjectCollection(this);
-    this.bounds = new tv.b.Range();
+    this.objects = new tr.model.ObjectCollection(this);
+    this.bounds = new tr.b.Range();
     this.sortIndex = 0;
   };
 
@@ -49,11 +49,8 @@
   };
 
   ProcessBase.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+    __proto__: tr.model.EventContainer.prototype,
 
-    /*
-     * @return {Number} A globally unique identifier for this counter.
-     */
     get guid() {
       return this.guid_;
     },
diff --git a/trace-viewer/trace_viewer/model/process_memory_dump.html b/trace-viewer/trace_viewer/model/process_memory_dump.html
new file mode 100644
index 0000000..afdaa6a
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/process_memory_dump.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/base/units/util.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/container_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the ProcessMemoryDump class.
+ */
+tr.exportTo('tr.model', function() {
+
+  function getValidSizeAttributeOrUndefined(memoryAllocatorDump, opt_model) {
+    var sizeAttr = memoryAllocatorDump.attributes['size'];
+    if (sizeAttr === undefined)
+      return undefined;
+
+    if (!(sizeAttr instanceof tr.model.ScalarAttribute)) {
+      if (opt_model !== undefined) {
+        opt_model.importWarning({
+          type: 'memory_dump_parse_error',
+          message: '\'size\' attribute of memory allocator dump \'' +
+              memoryAllocatorDump.fullName + '\' is not a scalar.'
+        });
+      }
+      return undefined;
+    }
+
+    return sizeAttr;
+  }
+
+  /**
+   * The ProcessMemoryDump represents a memory dump of a single process.
+   * @constructor
+   */
+  function ProcessMemoryDump(globalMemoryDump, process, start) {
+    tr.model.ContainerMemoryDump.call(this, start);
+    this.process = process;
+    this.globalMemoryDump = globalMemoryDump;
+
+    this.totalResidentBytes = undefined;
+    this.vmRegions_ = undefined;
+
+    this.tracingMemoryDiscounted_ = false;
+  };
+
+  ProcessMemoryDump.prototype = {
+    __proto__: tr.model.ContainerMemoryDump.prototype,
+
+    get userFriendlyName() {
+      return 'Process memory dump at ' + tr.b.units.tsString(this.start);
+    },
+
+    get vmRegions() {
+      throw new Error(
+          'VM regions must be accessed through the mostRecentVmRegions field');
+    },
+
+    set vmRegions(vmRegions) {
+      this.vmRegions_ = vmRegions;
+    },
+
+    getMostRecentTotalVmRegionStat: function(statName) {
+      if (this.mostRecentVmRegions === undefined)
+        return undefined;
+
+      var total = 0;
+      this.mostRecentVmRegions.forEach(function(vmRegion) {
+        var statValue = vmRegion.byteStats[statName];
+        if (statValue === undefined)
+          return;
+        total += statValue;
+      });
+      return total;
+    },
+
+    discountTracingOverhead: function(opt_model) {
+      // Make sure that calling this method twice won't lead to
+      // 'double-discounting'.
+      if (this.tracingMemoryDiscounted_)
+        return;
+      this.tracingMemoryDiscounted_ = true;
+
+      var tracingDump = this.getMemoryAllocatorDumpByFullName('tracing');
+      if (tracingDump === undefined)
+        return;
+
+      var tracingSizeAttr = getValidSizeAttributeOrUndefined(
+          tracingDump, opt_model);
+      if (tracingSizeAttr === undefined)
+        return;
+
+      var tracingSize = tracingSizeAttr.value;
+
+      // Subtract the tracing size from the total.
+      if (this.totalResidentBytes !== undefined)
+        this.totalResidentBytes -= tracingSize;
+
+      // Subtract the tracing size from VM regions.
+      if (this.vmRegions_ !== undefined) {
+        this.vmRegions_.push(VMRegion.fromDict({
+          mappedFile: '[discounted tracing overhead]',
+          byteStats: {
+            privateDirtyResident: -tracingSize,
+            proportionalResident: -tracingSize
+          }
+        }));
+      }
+
+      // Subtract the tracing size from the 'malloc' MemoryAllocatorDump.
+      var mallocDump = this.getMemoryAllocatorDumpByFullName('malloc');
+      if (mallocDump !== undefined) {
+        var overheadSizeAttribute = new tr.model.ScalarAttribute(
+            'bytes', -tracingSize);
+        var overheadDump = new tr.model.MemoryAllocatorDump(
+            this, 'malloc/discounted_tracing_overhead');
+        overheadDump.parent = mallocDump;
+        overheadDump.addAttribute('size', overheadSizeAttribute);
+        mallocDump.children.push(overheadDump);
+
+        var mallocDumpSizeAttr = getValidSizeAttributeOrUndefined(
+            mallocDump, opt_model);
+        if (mallocDumpSizeAttr !== undefined)
+          mallocDumpSizeAttr.value -= tracingSize;
+
+        // Force rebuilding the memory allocator dump index (as we've just
+        // added a new memory allocator dump).
+        this.memoryAllocatorDumps = this.memoryAllocatorDumps;
+      }
+    }
+  };
+
+  ProcessMemoryDump.hookUpMostRecentVmRegionsLinks = function(processDumps) {
+    var mostRecentVmRegions = undefined;
+
+    processDumps.forEach(function(processDump) {
+      // Update the most recent VM regions from the current dump.
+      if (processDump.vmRegions_ !== undefined)
+        mostRecentVmRegions = processDump.vmRegions_;
+
+      // Set the most recent VM regions of the current dump.
+      processDump.mostRecentVmRegions = mostRecentVmRegions;
+    });
+  };
+
+  /**
+   * @constructor
+   */
+  function VMRegion(startAddress, sizeInBytes, protectionFlags,
+      mappedFile, byteStats) {
+    this.startAddress = startAddress;
+    this.sizeInBytes = sizeInBytes;
+    this.protectionFlags = protectionFlags;
+    this.mappedFile = mappedFile;
+    this.byteStats = byteStats;
+  };
+
+  VMRegion.PROTECTION_FLAG_READ = 4;
+  VMRegion.PROTECTION_FLAG_WRITE = 2;
+  VMRegion.PROTECTION_FLAG_EXECUTE = 1;
+
+  VMRegion.prototype = {
+    get protectionFlagsToString() {
+      if (this.protectionFlags === undefined)
+        return undefined;
+      return (
+          (this.protectionFlags & VMRegion.PROTECTION_FLAG_READ ? 'r' : '-') +
+          (this.protectionFlags & VMRegion.PROTECTION_FLAG_WRITE ? 'w' : '-') +
+          (this.protectionFlags & VMRegion.PROTECTION_FLAG_EXECUTE ? 'x' : '-')
+      );
+    }
+  };
+
+  VMRegion.fromDict = function(dict) {
+    return new VMRegion(
+        dict.startAddress,
+        dict.sizeInBytes,
+        dict.protectionFlags,
+        dict.mappedFile,
+        VMRegionByteStats.fromDict(dict.byteStats));
+  };
+
+  /**
+   * @constructor
+   */
+  function VMRegionByteStats(privateCleanResident, privateDirtyResident,
+                             sharedCleanResident, sharedDirtyResident,
+                             proportionalResident, swapped) {
+    this.privateCleanResident = privateCleanResident;
+    this.privateDirtyResident = privateDirtyResident;
+    this.sharedCleanResident = sharedCleanResident;
+    this.sharedDirtyResident = sharedDirtyResident;
+    this.proportionalResident = proportionalResident;
+    this.swapped = swapped;
+  }
+
+  VMRegionByteStats.fromDict = function(dict) {
+    return new VMRegionByteStats(
+        dict.privateCleanResident,
+        dict.privateDirtyResident,
+        dict.sharedCleanResident,
+        dict.sharedDirtyResident,
+        dict.proportionalResident,
+        dict.swapped);
+  }
+
+  tr.model.EventRegistry.register(
+      ProcessMemoryDump,
+      {
+        name: 'processMemoryDump',
+        pluralName: 'processMemoryDumps',
+        singleViewElementName: 'tr-c-a-single-process-memory-dump-sub-view',
+        multiViewElementName: 'tr-c-a-multi-process-memory-dump-sub-view'
+      });
+
+  return {
+    ProcessMemoryDump: ProcessMemoryDump,
+    VMRegion: VMRegion,
+    VMRegionByteStats: VMRegionByteStats
+  };
+});
+</script>
diff --git a/trace-viewer/trace_viewer/model/process_memory_dump_test.html b/trace-viewer/trace_viewer/model/process_memory_dump_test.html
new file mode 100644
index 0000000..f058190
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/process_memory_dump_test.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 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="import" href="/core/test_utils.html">
+<link rel="import" href="/model/attribute.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/global_memory_dump.html">
+<link rel="import" href="/model/memory_allocator_dump.html">
+<link rel="import" href="/model/process_memory_dump.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  var GlobalMemoryDump = tr.model.GlobalMemoryDump;
+  var ProcessMemoryDump = tr.model.ProcessMemoryDump;
+  var MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+  var VMRegion = tr.model.VMRegion;
+  var ScalarAttribute = tr.model.ScalarAttribute;
+
+  var createProcessMemoryDump = function(timestamp, model) {
+    var gmd = new GlobalMemoryDump(model, timestamp);
+    model.globalMemoryDumps.push(gmd);
+    var p = model.getOrCreateProcess(123);
+    var pmd = new ProcessMemoryDump(gmd, p, timestamp + 1);
+    gmd.processMemoryDumps[123] = pmd;
+    p.memoryDumps.push(pmd);
+    return pmd;
+  }
+
+  var createFinalizedProcessMemoryDump = function(timestamp, createdCallback) {
+    return createFinalizedProcessMemoryDumps([timestamp], function(pmds) {
+      createdCallback(pmds[0]);
+    })[0];
+  }
+
+  function createFinalizedProcessMemoryDumps(timestamps, createdCallback) {
+    var model = tr.c.test_utils.newModel(function(model) {
+      var pmds = timestamps.map(function(timestamp) {
+        return createProcessMemoryDump(timestamp, model);
+      });
+      createdCallback(pmds);
+    });
+    var pmds = model.getProcess(123).memoryDumps;
+    assert.lengthOf(pmds, timestamps.length);
+    return pmds;
+  }
+
+  function checkProtectionFlagsToString(protectionFlags, expectedString) {
+    var vmRegion = VMRegion.fromDict({
+      startAddress: 256,
+      sizeInBytes: 336,
+      protectionFlags: protectionFlags,
+      mappedFile: '[stack:20310]',
+      byteStats: {
+        privateDirtyResident: 96,
+        swapped: 144,
+        proportionalResident: 158
+      }
+    });
+    assert.strictEqual(vmRegion.protectionFlagsToString, expectedString);
+  }
+
+  test('totalResidentSizeInBytes_undefinedVmRegions', function() {
+    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {});
+    assert.isUndefined(pmd.mostRecentTotalProportionalResidentSizeInBytes);
+    assert.isUndefined(
+        pmd.getMostRecentTotalVmRegionStat('privateDirtyResident'));
+    assert.isUndefined(
+        pmd.getMostRecentTotalVmRegionStat('privateCleanResident'));
+  });
+
+  test('totalResidentSizeInBytes_zeroVmRegions', function() {
+    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+      pmd.vmRegions = [];
+    });
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('proportionalResident'), 0);
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('privateDirtyResident'), 0);
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('privateCleanResident'), 0);
+  });
+
+  test('totalResidentSizeInBytes_oneVmRegion', function() {
+    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+      pmd.vmRegions = [
+        VMRegion.fromDict({
+          startAddress: 256,
+          sizeInBytes: 336,
+          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+              VMRegion.PROTECTION_FLAG_WRITE,
+          mappedFile: '[stack:20310]',
+          byteStats: {
+            privateDirtyResident: 96,
+            swapped: 144,
+            proportionalResident: 158
+          }
+        })
+      ];
+    });
+    assert.equal(
+        pmd.getMostRecentTotalVmRegionStat('proportionalResident'), 158);
+    assert.equal(
+        pmd.getMostRecentTotalVmRegionStat('privateDirtyResident'), 96);
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('privateCleanResident'), 0);
+  });
+
+  test('totalResidentSizeInBytes_twoVmRegions', function() {
+    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+      pmd.vmRegions = [
+        VMRegion.fromDict({
+          startAddress: 256,
+          sizeInBytes: 336,
+          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+              VMRegion.PROTECTION_FLAG_WRITE,
+          mappedFile: '[stack:20310]',
+          byteStats: {
+            privateDirtyResident: 96,
+            swapped: 144,
+            proportionalResident: 158
+          }
+        }),
+        VMRegion.fromDict({
+          startAddress: 848,
+          sizeInBytes: 592,
+          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+              VMRegion.PROTECTION_FLAG_EXECUTE,
+          mappedFile: '/dev/ashmem/dalvik',
+          byteStats: {
+            privateDirtyResident: 205,
+            privateCleanResident: 0,
+            proportionalResident: 205
+          }
+        })
+      ];
+    });
+    assert.equal(
+        pmd.getMostRecentTotalVmRegionStat('proportionalResident'), 363);
+    assert.equal(
+        pmd.getMostRecentTotalVmRegionStat('privateDirtyResident'), 301);
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('swapped'), 144);
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('privateCleanResident'), 0);
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('sharedCleanResident'), 0);
+  });
+
+  test('hookUpMostRecentVmRegionsLinks_emptyArray', function() {
+    var dumps = [];
+    ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(dumps);
+    assert.lengthOf(dumps, 0);
+  });
+
+  test('hookUpMostRecentVmRegionsLinks_nonEmptyArray', function() {
+    var m = new tr.Model();
+
+    // A dump with no VM regions or allocator dumps.
+    var dump1 = createProcessMemoryDump(1, m);
+
+    // A dump with VM regions and malloc and Oilpan allocator dumps.
+    var dump2 = createProcessMemoryDump(2, m);
+    dump2.vmRegions = [];
+    dump2.memoryAllocatorDumps = (function() {
+      var oilpanDump = new MemoryAllocatorDump('oilpan');
+      oilpanDump.addAttribute('size', new ScalarAttribute('bytes', 1024));
+      oilpanDump.addAttribute('objects_count',
+          new ScalarAttribute('objects', 7));
+      oilpanDump.addAttribute('inner_size', new ScalarAttribute('bytes', 768));
+
+      var v8Dump = new MemoryAllocatorDump('v8');
+      v8Dump.addAttribute('size', new ScalarAttribute('bytes', 2048));
+      v8Dump.addAttribute('objects_count', new ScalarAttribute('objects', 15));
+      v8Dump.addAttribute('inner_size', new ScalarAttribute('bytes', 1999));
+
+      return [oilpanDump. v8Dump];
+    })();
+
+    // A dump with malloc and V8 allocator dumps.
+    var dump3 = createProcessMemoryDump(3, m);
+    dump3.memoryAllocatorDumps = (function() {
+      var mallocDump = new MemoryAllocatorDump('malloc');
+      mallocDump.addAttribute('size', new ScalarAttribute('bytes', 1024));
+      mallocDump.addAttribute('objects_count',
+          new ScalarAttribute('objects', 7));
+      mallocDump.addAttribute('inner_size', new ScalarAttribute('bytes', 768));
+
+      var v8Dump = new MemoryAllocatorDump('v8');
+      v8Dump.addAttribute('size', new ScalarAttribute('bytes', 2048));
+      v8Dump.addAttribute('objects_count', new ScalarAttribute('objects', 15));
+      v8Dump.addAttribute('inner_size', new ScalarAttribute('bytes', 1999));
+
+      return [mallocDump. v8Dump];
+    })();
+
+    // A dump with VM regions.
+    var dump4 = createProcessMemoryDump(4, m);
+    dump4.vmRegions = [
+      VMRegion.fromDict({
+        startAddress: 256,
+        sizeInBytes: 336,
+        protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+            VMRegion.PROTECTION_FLAG_WRITE,
+        mappedFile: '[stack:20310]',
+        byteStats: {
+          privateResident: 96,
+          sharedResident: 144,
+          proportionalResident: 158
+        }
+      })
+    ];
+
+    var dumps = [dump1, dump2, dump3, dump4];
+    ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(dumps);
+
+    assert.lengthOf(dumps, 4);
+
+    assert.equal(dumps[0], dump1);
+    assert.isUndefined(dump1.mostRecentVmRegions);
+
+    assert.equal(dumps[1], dump2);
+    assert.equal(dump2.mostRecentVmRegions, dump2.vmRegions_);
+
+    assert.equal(dumps[2], dump3);
+    assert.equal(dump3.mostRecentVmRegions, dump2.vmRegions_);
+
+    assert.equal(dumps[3], dump4);
+    assert.equal(dump4.mostRecentVmRegions, dump4.vmRegions_);
+  });
+
+  test('vmRegion_protectionFlagsToString', function() {
+    checkProtectionFlagsToString(undefined, undefined);
+    checkProtectionFlagsToString(0, '---');
+    checkProtectionFlagsToString(VMRegion.PROTECTION_FLAG_READ, 'r--');
+    checkProtectionFlagsToString(
+        VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_EXECUTE,
+        'r-x');
+    checkProtectionFlagsToString(
+        VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_WRITE,
+        'rw-');
+  });
+
+  test('checkDiscountTracingOverhead_undefinedFields', function() {
+    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+      var v8Dump = new MemoryAllocatorDump(pmd, 'v8');
+      v8Dump.addAttribute('size', new ScalarAttribute('bytes', 2048));
+
+      var tracingDump = new MemoryAllocatorDump(pmd, 'tracing');
+      tracingDump.addAttribute('size', new ScalarAttribute('bytes', 1024));
+
+      pmd.memoryAllocatorDumps = [v8Dump, tracingDump];
+    });
+
+    assert.isUndefined(pmd.totalResidentBytes);
+    assert.isUndefined(
+        pmd.getMostRecentTotalVmRegionStat('proportionalResident'));
+
+    var v8Dump = pmd.getMemoryAllocatorDumpByFullName('v8');
+    assert.equal(v8Dump.attributes['size'].value, 2048);
+
+    var tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing');
+    assert.equal(tracingDump.attributes['size'].value, 1024);
+  });
+
+  test('checkDiscountTracingOverhead_definedFields', function() {
+    var pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+      pmd.totalResidentBytes = 10240;
+
+      pmd.vmRegions = [
+        VMRegion.fromDict({
+          startAddress: 256,
+          sizeInBytes: 6000,
+          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+              VMRegion.PROTECTION_FLAG_WRITE,
+          mappedFile: '[stack:20310]',
+          byteStats: {
+            privateDirtyResident: 4096,
+            swapped: 1536,
+            proportionalResident: 5120
+          }
+        })
+      ];
+
+      var mallocDump = new MemoryAllocatorDump(pmd, 'malloc');
+      mallocDump.addAttribute('size', new ScalarAttribute('bytes', 3072));
+
+      var tracingDump = new MemoryAllocatorDump(pmd, 'tracing');
+      tracingDump.addAttribute('size', new ScalarAttribute('bytes', 1024));
+
+      pmd.memoryAllocatorDumps = [mallocDump, tracingDump];
+    });
+
+    assert.equal(pmd.totalResidentBytes, 9216);
+
+    assert.equal(
+        pmd.getMostRecentTotalVmRegionStat('privateDirtyResident'), 3072);
+    assert.equal(pmd.getMostRecentTotalVmRegionStat('swapped'), 1536);
+    assert.equal(
+        pmd.getMostRecentTotalVmRegionStat('proportionalResident'), 4096);
+
+    var mallocDump = pmd.getMemoryAllocatorDumpByFullName('malloc');
+    assert.equal(mallocDump.attributes['size'].value, 2048);
+
+    var tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing');
+    assert.equal(tracingDump.attributes['size'].value, 1024);
+  });
+
+  test('checkDiscountTracingOverhead_withMostRecentVmRegionsLinks', function() {
+    var pmds = createFinalizedProcessMemoryDumps([42, 90], function(pmds) {
+      pmds[0].totalResidentBytes = 1000;
+      pmds[0].vmRegions = [
+        VMRegion.fromDict({
+          startAddress: 256,
+          sizeInBytes: 6000,
+          protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+              VMRegion.PROTECTION_FLAG_WRITE,
+          mappedFile: '[stack:20310]',
+          byteStats: {
+            privateDirtyResident: 4096
+          }
+        })
+      ];
+      pmds[0].memoryAllocatorDumps = (function() {
+        var tracingDump = new MemoryAllocatorDump(pmds[0], 'tracing');
+        tracingDump.addAttribute('size', new ScalarAttribute('bytes', 100));
+        return [tracingDump];
+      })();
+
+      pmds[1].totalResidentBytes = 2000;
+      pmds[1].memoryAllocatorDumps = (function() {
+        var tracingDump = new MemoryAllocatorDump(pmds[0], 'tracing');
+        tracingDump.addAttribute('size', new ScalarAttribute('bytes', 200));
+        return [tracingDump];
+      })();
+    });
+
+    // First PMD: Both total resident and private dirty resident size should be
+    // reduced by 100.
+    assert.equal(pmds[0].totalResidentBytes, 900);
+    assert.equal(
+        pmds[0].getMostRecentTotalVmRegionStat('privateDirtyResident'), 3996);
+
+    // Second PMD: Total resident size should be reduced by 200, whereas private
+    // dirty resident size should be reduced by 100 (because it comes from
+    // the VM regions in the first dump).
+    assert.equal(pmds[1].totalResidentBytes, 1800);
+    assert.equal(
+        pmds[1].getMostRecentTotalVmRegionStat('privateDirtyResident'), 3996);
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/process_test.html b/trace-viewer/trace_viewer/model/process_test.html
similarity index 61%
rename from trace-viewer/trace_viewer/core/trace_model/process_test.html
rename to trace-viewer/trace_viewer/model/process_test.html
index f3d8e88..f382ffa 100644
--- a/trace-viewer/trace_viewer/core/trace_model/process_test.html
+++ b/trace-viewer/trace_viewer/model/process_test.html
@@ -6,24 +6,24 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
-<link rel="import" href="/core/trace_model/process.html">
+<link rel="import" href="/model/model.html">
+<link rel="import" href="/model/process.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   test('getOrCreateCounter', function() {
-    var model = new tv.c.TraceModel();
-    var process = new tv.c.trace_model.Process(model, 7);
+    var model = new tr.Model();
+    var process = new tr.model.Process(model, 7);
     var ctrBar = process.getOrCreateCounter('foo', 'bar');
     var ctrBar2 = process.getOrCreateCounter('foo', 'bar');
     assert.equal(ctrBar2, ctrBar);
   });
 
   test('shiftTimestampsForward', function() {
-    var model = new tv.c.TraceModel();
-    var process = new tv.c.trace_model.Process(model, 7);
+    var model = new tr.Model();
+    var process = new tr.model.Process(model, 7);
     var ctr = process.getOrCreateCounter('foo', 'bar');
     var thread = process.getOrCreateThread(1);
 
@@ -41,47 +41,47 @@
   });
 
   test('compareOnPID', function() {
-    var model = new tv.c.TraceModel();
-    var p1 = new tv.c.trace_model.Process(model, 1);
+    var model = new tr.Model();
+    var p1 = new tr.model.Process(model, 1);
     p1.name = 'Renderer';
 
-    var model = new tv.c.TraceModel();
-    var p2 = new tv.c.trace_model.Process(model, 2);
+    var model = new tr.Model();
+    var p2 = new tr.model.Process(model, 2);
     p2.name = 'Renderer';
 
     assert.isBelow(p1.compareTo(p2), 0);
   });
 
   test('compareOnSortIndex', function() {
-    var model = new tv.c.TraceModel();
-    var p1 = new tv.c.trace_model.Process(model, 1);
+    var model = new tr.Model();
+    var p1 = new tr.model.Process(model, 1);
     p1.name = 'Renderer';
     p1.sortIndex = 1;
 
-    var p2 = new tv.c.trace_model.Process(model, 2);
+    var p2 = new tr.model.Process(model, 2);
     p2.name = 'Renderer';
 
     assert.isAbove(p1.compareTo(p2), 0);
   });
 
   test('compareOnName', function() {
-    var model = new tv.c.TraceModel();
-    var p1 = new tv.c.trace_model.Process(model, 1);
+    var model = new tr.Model();
+    var p1 = new tr.model.Process(model, 1);
     p1.name = 'Browser';
 
-    var p2 = new tv.c.trace_model.Process(model, 2);
+    var p2 = new tr.model.Process(model, 2);
     p2.name = 'Renderer';
 
     assert.isBelow(p1.compareTo(p2), 0);
   });
 
   test('compareOnLabels', function() {
-    var model = new tv.c.TraceModel();
-    var p1 = new tv.c.trace_model.Process(model, 1);
+    var model = new tr.Model();
+    var p1 = new tr.model.Process(model, 1);
     p1.name = 'Renderer';
     p1.labels = ['a'];
 
-    var p2 = new tv.c.trace_model.Process(model, 2);
+    var p2 = new tr.model.Process(model, 2);
     p2.name = 'Renderer';
     p2.labels = ['b'];
 
diff --git a/trace-viewer/trace_viewer/core/trace_model/proxy_selectable_item.html b/trace-viewer/trace_viewer/model/proxy_selectable_item.html
similarity index 74%
rename from trace-viewer/trace_viewer/core/trace_model/proxy_selectable_item.html
rename to trace-viewer/trace_viewer/model/proxy_selectable_item.html
index e6715e9..9ae9fee 100644
--- a/trace-viewer/trace_viewer/core/trace_model/proxy_selectable_item.html
+++ b/trace-viewer/trace_viewer/model/proxy_selectable_item.html
@@ -5,15 +5,15 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/selectable_item.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/selectable_item.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
-  var SelectableItem = tv.c.trace_model.SelectableItem;
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.exportTo('tr.model', function() {
+  var SelectableItem = tr.model.SelectableItem;
+  var SelectionState = tr.model.SelectionState;
 
   /**
    * A ProxySelectableItem is a selectable item which is not a model item itself
diff --git a/trace-viewer/trace_viewer/core/trace_model/proxy_selectable_item_test.html b/trace-viewer/trace_viewer/model/proxy_selectable_item_test.html
similarity index 78%
rename from trace-viewer/trace_viewer/core/trace_model/proxy_selectable_item_test.html
rename to trace-viewer/trace_viewer/model/proxy_selectable_item_test.html
index 88bf61e..d5367e3 100644
--- a/trace-viewer/trace_viewer/core/trace_model/proxy_selectable_item_test.html
+++ b/trace-viewer/trace_viewer/model/proxy_selectable_item_test.html
@@ -6,15 +6,15 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/proxy_selectable_item.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/proxy_selectable_item.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ProxySelectableItem = tv.c.trace_model.ProxySelectableItem;
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.b.unittest.testSuite(function() {
+  var ProxySelectableItem = tr.model.ProxySelectableItem;
+  var SelectionState = tr.model.SelectionState;
 
   test('checkSelectionState_undefinedModelItem', function() {
     var proxyItem = new ProxySelectableItem(undefined);
diff --git a/trace-viewer/trace_viewer/core/trace_model/rect_annotation.html b/trace-viewer/trace_viewer/model/rect_annotation.html
similarity index 67%
rename from trace-viewer/trace_viewer/core/trace_model/rect_annotation.html
rename to trace-viewer/trace_viewer/model/rect_annotation.html
index 605f8ab..7257451 100644
--- a/trace-viewer/trace_viewer/core/trace_model/rect_annotation.html
+++ b/trace-viewer/trace_viewer/model/rect_annotation.html
@@ -6,16 +6,16 @@
 -->
 
 <link rel="import" href="/core/location.html">
-<link rel="import" href="/core/trace_model/annotation.html">
+<link rel="import" href="/model/annotation.html">
 <link rel="import" href="/core/tracks/rect_annotation_view.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   function RectAnnotation(start, end) {
-    tv.c.trace_model.Annotation.apply(this, arguments);
+    tr.model.Annotation.apply(this, arguments);
 
     this.startLocation_ = start; // Location of top-left corner.
     this.endLocation_ = end; // Location of bottom-right corner.
@@ -25,14 +25,14 @@
   RectAnnotation.fromDict = function(dict) {
     var args = dict.args;
     var startLoc =
-        new tv.c.Location(args.start.xWorld, args.start.yComponents);
+        new tr.c.Location(args.start.xWorld, args.start.yComponents);
     var endLoc =
-        new tv.c.Location(args.end.xWorld, args.end.yComponents);
-    return new tv.c.trace_model.RectAnnotation(startLoc, endLoc);
+        new tr.c.Location(args.end.xWorld, args.end.yComponents);
+    return new tr.model.RectAnnotation(startLoc, endLoc);
   }
 
   RectAnnotation.prototype = {
-    __proto__: tv.c.trace_model.Annotation.prototype,
+    __proto__: tr.model.Annotation.prototype,
 
     get startLocation() {
       return this.startLocation_;
@@ -53,11 +53,11 @@
     },
 
     createView_: function(viewport) {
-      return new tv.c.annotations.RectAnnotationView(viewport, this);
+      return new tr.c.annotations.RectAnnotationView(viewport, this);
     }
   };
 
-  tv.c.trace_model.Annotation.register(RectAnnotation, {typeName: 'rect'});
+  tr.model.Annotation.register(RectAnnotation, {typeName: 'rect'});
 
   return {
     RectAnnotation: RectAnnotation
diff --git a/trace-viewer/trace_viewer/core/trace_model/sample.html b/trace-viewer/trace_viewer/model/sample.html
similarity index 74%
rename from trace-viewer/trace_viewer/core/trace_model/sample.html
rename to trace-viewer/trace_viewer/model/sample.html
index c4b6571..3c42915 100644
--- a/trace-viewer/trace_viewer/core/trace_model/sample.html
+++ b/trace-viewer/trace_viewer/model/sample.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/timed_event.html">
+<link rel="import" href="/model/timed_event.html">
 
 <script>
 'use strict';
@@ -13,7 +13,7 @@
 /**
  * @fileoverview Provides the Sample class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * A Sample represents a sample taken at an instant in time, plus its stack
    * frame and parameters associated with that sample.
@@ -22,7 +22,7 @@
    */
   function Sample(cpu, thread, title, start, leafStackFrame,
                   opt_weight, opt_args) {
-    tv.c.trace_model.TimedEvent.call(this, start);
+    tr.model.TimedEvent.call(this, start);
 
     this.title = title;
     this.cpu = cpu;
@@ -33,7 +33,7 @@
   }
 
   Sample.prototype = {
-    __proto__: tv.c.trace_model.TimedEvent.prototype,
+    __proto__: tr.model.TimedEvent.prototype,
 
     get colorId() {
       return this.leafStackFrame.colorId;
@@ -49,17 +49,17 @@
 
     get userFriendlyName() {
       return 'Sample ' + ' at ' +
-          tv.c.analysis.tsString(this.start);
+          tr.b.units.tsString(this.start);
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       Sample,
       {
         name: 'sample',
         pluralName: 'samples',
-        singleViewElementName: 'tv-c-single-sample-sub-view',
-        multiViewElementName: 'tv-c-multi-sample-sub-view'
+        singleViewElementName: 'tr-c-a-single-sample-sub-view',
+        multiViewElementName: 'tr-c-a-multi-sample-sub-view'
       });
 
   return {
diff --git a/trace-viewer/trace_viewer/core/trace_model/sample_test.html b/trace-viewer/trace_viewer/model/sample_test.html
similarity index 66%
rename from trace-viewer/trace_viewer/core/trace_model/sample_test.html
rename to trace-viewer/trace_viewer/model/sample_test.html
index 5372612..a5ea1d7 100644
--- a/trace-viewer/trace_viewer/core/trace_model/sample_test.html
+++ b/trace-viewer/trace_viewer/model/sample_test.html
@@ -6,21 +6,21 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Sample = tv.c.trace_model.Sample;
-  var StackFrame = tv.c.trace_model.StackFrame;
-  var Thread = tv.c.trace_model.Thread;
+tr.b.unittest.testSuite(function() {
+  var Sample = tr.model.Sample;
+  var StackFrame = tr.model.StackFrame;
+  var Thread = tr.model.Thread;
 
   test('sampleStackTrace', function() {
     var thread = new Thread({}, 1);
 
-    var model = new tv.c.TraceModel();
-    var fABC = tv.c.test_utils.newStackTrace(model, 'cat', ['a', 'b', 'c']);
+    var model = new tr.Model();
+    var fABC = tr.c.test_utils.newStackTrace(model, 'cat', ['a', 'b', 'c']);
 
     var s = new Sample(undefined, thread, 'instructions_retired',
                        10, fABC, 10);
diff --git a/trace-viewer/trace_viewer/core/trace_model/selectable_item.html b/trace-viewer/trace_viewer/model/selectable_item.html
similarity index 87%
rename from trace-viewer/trace_viewer/core/trace_model/selectable_item.html
rename to trace-viewer/trace_viewer/model/selectable_item.html
index 7eeff97..6923cbd 100644
--- a/trace-viewer/trace_viewer/core/trace_model/selectable_item.html
+++ b/trace-viewer/trace_viewer/model/selectable_item.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
@@ -13,8 +13,8 @@
 /**
  * @fileoverview Provides the SelectableItem class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var SelectionState = tv.c.trace_model.SelectionState;
+tr.exportTo('tr.model', function() {
+  var SelectionState = tr.model.SelectionState;
 
   /**
    * A SelectableItem is the abstract base class for any non-container data that
diff --git a/trace-viewer/trace_viewer/core/trace_model/selectable_item_test.html b/trace-viewer/trace_viewer/model/selectable_item_test.html
similarity index 86%
rename from trace-viewer/trace_viewer/core/trace_model/selectable_item_test.html
rename to trace-viewer/trace_viewer/model/selectable_item_test.html
index 4c2328e..8cc83e3 100644
--- a/trace-viewer/trace_viewer/core/trace_model/selectable_item_test.html
+++ b/trace-viewer/trace_viewer/model/selectable_item_test.html
@@ -6,17 +6,17 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/event.html">
-<link rel="import" href="/core/trace_model/selectable_item.html">
-<link rel="import" href="/core/trace_model/selection_state.html">
+<link rel="import" href="/model/event.html">
+<link rel="import" href="/model/selectable_item.html">
+<link rel="import" href="/model/selection_state.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var SelectableItem = tv.c.trace_model.SelectableItem;
-  var SelectionState = tv.c.trace_model.SelectionState;
-  var Event = tv.c.trace_model.Event;
+tr.b.unittest.testSuite(function() {
+  var SelectableItem = tr.model.SelectableItem;
+  var SelectionState = tr.model.SelectionState;
+  var Event = tr.model.Event;
 
   function buildEventToTrackMap() {
     var eventToTrackMap = {
diff --git a/trace-viewer/trace_viewer/core/trace_model/selection_state.html b/trace-viewer/trace_viewer/model/selection_state.html
similarity index 92%
rename from trace-viewer/trace_viewer/core/trace_model/selection_state.html
rename to trace-viewer/trace_viewer/model/selection_state.html
index 3a4daf1..8fa3da7 100644
--- a/trace-viewer/trace_viewer/core/trace_model/selection_state.html
+++ b/trace-viewer/trace_viewer/model/selection_state.html
@@ -13,7 +13,7 @@
 /**
  * @fileoverview Provides the SelectionState class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   /**
    * The SelectionState enum defines how selectable items are displayed in the
diff --git a/trace-viewer/trace_viewer/core/trace_model/single_async_slice_sub_view_test.html b/trace-viewer/trace_viewer/model/single_async_slice_sub_view_test.html
similarity index 73%
rename from trace-viewer/trace_viewer/core/trace_model/single_async_slice_sub_view_test.html
rename to trace-viewer/trace_viewer/model/single_async_slice_sub_view_test.html
index 2b582ea..cdba33a 100644
--- a/trace-viewer/trace_viewer/core/trace_model/single_async_slice_sub_view_test.html
+++ b/trace-viewer/trace_viewer/model/single_async_slice_sub_view_test.html
@@ -8,16 +8,16 @@
 <link rel="import" href="/core/analysis/single_async_slice_sub_view.html">
 <link rel="import" href="/core/test_utils.html">
 <link rel="import" href="/core/selection.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var newAsyncSliceEx = tv.c.test_utils.newAsyncSliceEx;
+tr.b.unittest.testSuite(function() {
+  var newAsyncSliceEx = tr.c.test_utils.newAsyncSliceEx;
 
   test('instantiate', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var p1 = model.getOrCreateProcess(1);
     var t1 = p1.getOrCreateThread(1);
     t1.asyncSliceGroup.push(newAsyncSliceEx({
@@ -29,10 +29,10 @@
       endThread: t1
     }));
 
-    var selection = new tv.c.Selection();
+    var selection = new tr.c.Selection();
     selection.push(t1.asyncSliceGroup.slices[0]);
 
-    var viewEl = document.createElement('tv-c-a-single-async-slice-sub-view');
+    var viewEl = document.createElement('tr-c-a-single-async-slice-sub-view');
     viewEl.selection = selection;
     this.addHTMLOutput(viewEl);
   });
diff --git a/trace-viewer/trace_viewer/model/slice.html b/trace-viewer/trace_viewer/model/slice.html
new file mode 100644
index 0000000..a1c0995
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/slice.html
@@ -0,0 +1,221 @@
+<!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="import" href="/model/timed_event.html">
+<link rel="import" href="/base/units/util.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Slice class.
+ */
+tr.exportTo('tr.model', function() {
+  /**
+   * A Slice represents an interval of time plus parameters associated
+   * with that interval.
+   *
+   * @constructor
+   */
+  function Slice(category, title, colorId, start, args, opt_duration,
+                 opt_cpuStart, opt_cpuDuration) {
+    tr.model.TimedEvent.call(this, start);
+
+    this.category = category || '';
+    this.title = title;
+    this.colorId = colorId;
+    this.args = args;
+    this.startStackFrame = undefined;
+    this.endStackFrame = undefined;
+    this.didNotFinish = false;
+    this.inFlowEvents = [];
+    this.outFlowEvents = [];
+    this.subSlices = [];
+    this.selfTime = undefined;
+    this.cpuSelfTime = undefined;
+    this.important = false;
+    this.parentContainer = undefined;
+
+    if (opt_duration !== undefined)
+      this.duration = opt_duration;
+
+    if (opt_cpuStart !== undefined)
+      this.cpuStart = opt_cpuStart;
+
+    if (opt_cpuDuration !== undefined)
+      this.cpuDuration = opt_cpuDuration;
+  }
+
+  Slice.prototype = {
+    __proto__: tr.model.TimedEvent.prototype,
+
+
+    get analysisTypeName() {
+      return this.title;
+    },
+
+    get userFriendlyName() {
+      return 'Slice ' + this.title + ' at ' +
+          tr.b.units.tsString(this.start);
+    },
+
+    findDescendentSlice: function(targetTitle) {
+      if (!this.subSlices)
+        return undefined;
+
+      for (var i = 0; i < this.subSlices.length; i++) {
+        if (this.subSlices[i].title == targetTitle)
+          return this.subSlices[i];
+        var slice = this.subSlices[i].findDescendentSlice(targetTitle);
+        if (slice) return slice;
+      }
+      return undefined;
+    },
+
+    get mostTopLevelSlice() {
+      var curSlice = this;
+      while (curSlice.parentSlice)
+        curSlice = curSlice.parentSlice;
+
+      return curSlice;
+    },
+
+    /**
+     * Obtains all subsequent slices of this slice.
+     *
+     * Subsequent slices are slices that get executed after a particular
+     * slice, i.e., all the functions that are called after the current one.
+     *
+     * For instance, E.iterateAllSubsequentSlices() in the following example:
+     * [     A          ]
+     * [ B][  D   ][ G  ]
+     *  [C] [E][F]  [H]
+     * will pass F, G, then H to the provided callback.
+     *
+     * The reason we need subsequent slices of a particular slice is that
+     * when there is flow event goes into, e.g., E, we only want to highlight
+     * E's subsequent slices to indicate the execution order.
+     *
+     * The idea to calculate the subsequent slices of slice E is to view
+     * the slice group as a tree where the top-level slice A is the root node.
+     * The preorder depth-first-search (DFS) order is naturally equivalent
+     * to the function call order. We just need to perform a DFS, and start
+     * recording the slices after we see the occurance of E.
+     */
+    iterateAllSubsequentSlices: function(callback, opt_this) {
+      var parentStack = [];
+      var started = false;
+
+      // get the root node and push it to the DFS stack
+      var topmostSlice = this.mostTopLevelSlice;
+      parentStack.push(topmostSlice);
+
+      // Using the stack to perform DFS
+      while (parentStack.length !== 0) {
+        var curSlice = parentStack.pop();
+
+        if (started)
+          callback.call(opt_this, curSlice);
+        else
+          started = (curSlice.guid === this.guid);
+
+        for (var i = curSlice.subSlices.length - 1; i >= 0; i--) {
+          parentStack.push(curSlice.subSlices[i]);
+        }
+      }
+    },
+
+    get subsequentSlices() {
+      var res = [];
+
+      this.iterateAllSubsequentSlices(function(subseqSlice) {
+        res.push(subseqSlice);
+      });
+
+      return res;
+    },
+
+    /**
+     * Obtains the parents of a slice, from the most immediate to the root.
+     *
+     * For instance, E.iterateAllAncestors() in the following example:
+     * [     A          ]
+     * [ B][  D   ][ G  ]
+     *  [C] [E][F]  [H]
+     * will pass D, then A to the provided callback, in the order from the
+     * leaves to the root.
+     */
+    iterateAllAncestors: function(callback, opt_this) {
+      var curSlice = this;
+
+      while (curSlice.parentSlice) {
+        curSlice = curSlice.parentSlice;
+        callback.call(opt_this, curSlice);
+      }
+    },
+
+    get ancestorSlices() {
+      var res = [];
+
+      this.iterateAllAncestors(function(ancestor) {
+        res.push(ancestor);
+      });
+
+      return res;
+    },
+
+    /**
+     * Returns this slice, and its ancestor and subsequent slices.
+     *
+     * For instance, E.ancestorAndSubsequentSlices in the following example:
+     * [     A          ]
+     * [ B][  D   ][ G  ]
+     *  [C] [E][F]  [H]
+     * will return E, D, A, F, G, and H, where E is itself, D and A are
+     * E's ancestors, and F, G, and H are subsequent slices of E
+     */
+    get ancestorAndSubsequentSlices() {
+      var res = [];
+
+      res.push(this);
+
+      this.iterateAllAncestors(function(aSlice) {
+        res.push(aSlice);
+      });
+
+      this.iterateAllSubsequentSlices(function(sSlice) {
+        res.push(sSlice);
+      });
+
+      return res;
+    },
+
+    iterateAllDescendents: function(callback, opt_this) {
+      this.subSlices.forEach(callback, opt_this);
+      this.subSlices.forEach(function(subSlice) {
+        subSlice.iterateAllDescendents(callback, opt_this);
+      }, opt_this);
+    },
+
+    get descendentSlices() {
+      var res = [];
+
+      this.iterateAllDescendents(function(des) {
+        res.push(des);
+      });
+
+      return res;
+    }
+
+  };
+
+  return {
+    Slice: Slice
+  };
+});
+</script>
+
diff --git a/trace-viewer/trace_viewer/core/trace_model/slice_group.html b/trace-viewer/trace_viewer/model/slice_group.html
similarity index 92%
rename from trace-viewer/trace_viewer/core/trace_model/slice_group.html
rename to trace-viewer/trace_viewer/model/slice_group.html
index 8da0b60..f8ad6a9 100644
--- a/trace-viewer/trace_viewer/core/trace_model/slice_group.html
+++ b/trace-viewer/trace_viewer/model/slice_group.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/event_container.html">
+<link rel="import" href="/model/event_container.html">
 <link rel="import" href="/core/filter.html">
 <link rel="import" href="/base/ui/color_scheme.html">
 <link rel="import" href="/base/guid.html">
@@ -17,8 +17,8 @@
 /**
  * @fileoverview Provides the SliceGroup class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var Slice = tv.c.trace_model.Slice;
+tr.exportTo('tr.model', function() {
+  var Slice = tr.model.Slice;
 
   function getSliceLo(s) {
     return s.start;
@@ -38,12 +38,12 @@
    * @constructor
    * @param {function(new:Slice, category, title, colorId, start, args)=}
    *     opt_sliceConstructor The constructor to use when creating slices.
-   * @extends {tv.c.trace_model.EventContainer}
+   * @extends {tr.model.EventContainer}
    */
-  function SliceGroup(parentThread, opt_sliceConstructor, opt_name) {
-    this.guid_ = tv.b.GUID.allocate();
+  function SliceGroup(parentContainer, opt_sliceConstructor, opt_name) {
+    this.guid_ = tr.b.GUID.allocate();
 
-    this.parentThread_ = parentThread;
+    this.parentContainer_ = parentContainer;
 
     var sliceConstructor = opt_sliceConstructor || Slice;
     this.sliceConstructor = sliceConstructor;
@@ -51,35 +51,35 @@
     this.openPartialSlices_ = [];
 
     this.slices = [];
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
     this.topLevelSlices = [];
     this.haveTopLevelSlicesBeenBuilt = false;
     this.name_ = opt_name;
   }
 
   SliceGroup.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+    __proto__: tr.model.EventContainer.prototype,
 
     get guid() {
       return this.guid_;
     },
 
-    get parentThread() {
-      return this.parentThread_;
+    get parentContainer() {
+      return this.parentContainer_;
     },
 
     get model() {
-      return this.parentThread_.parent.model;
+      return this.parentContainer_.parent.model;
     },
 
     get stableId() {
-      return this.parentThread_.stableId + '.SliceGroup';
+      return this.parentContainer_.stableId + '.SliceGroup';
     },
 
     getSettingsKey: function() {
       if (!this.name_)
         return undefined;
-      var parentKey = this.parentThread_.getSettingsKey();
+      var parentKey = this.parentContainer_.getSettingsKey();
       if (!parentKey)
         return undefined;
       return parentKey + '.' + this.name;
@@ -98,6 +98,7 @@
      */
     pushSlice: function(slice) {
       this.haveTopLevelSlicesBeenBuilt = false;
+      slice.parentContainer = this.parentContainer_;
       this.slices.push(slice);
       return slice;
     },
@@ -108,7 +109,10 @@
      */
     pushSlices: function(slices) {
       this.haveTopLevelSlicesBeenBuilt = false;
-      this.slices.push.apply(this.slices, slices);
+      slices.forEach(function(slice) {
+        slice.parentContainer = this.parentContainer_;
+        this.slices.push(slice);
+      }, this);
     },
 
     /**
@@ -131,7 +135,7 @@
           throw new Error('Slices must be added in increasing timestamp order');
       }
 
-      var colorId = tv.b.ui.getColorIdForGeneralPurposeString(title);
+      var colorId = tr.b.ui.getColorIdForGeneralPurposeString(title);
       var slice = new this.sliceConstructor(category, title, colorId, ts,
                                             opt_args ? opt_args : {}, null,
                                             opt_tts);
@@ -202,7 +206,7 @@
      */
     pushCompleteSlice: function(category, title, ts, duration, tts,
                                 cpuDuration, opt_args) {
-      var colorId = tv.b.ui.getColorIdForGeneralPurposeString(title);
+      var colorId = tr.b.ui.getColorIdForGeneralPurposeString(title);
       var slice = new this.sliceConstructor(category, title, colorId, ts,
                                             opt_args ? opt_args : {},
                                             duration, tts, cpuDuration);
@@ -282,7 +286,7 @@
 
     iterSlicesInTimeRange: function(callback, start, end) {
       var ret = [];
-      tv.b.iterateOverIntersectingIntervals(
+      tr.b.iterateOverIntersectingIntervals(
         this.topLevelSlices,
         function(s) { return s.start; },
         function(s) { return s.duration; },
@@ -298,7 +302,7 @@
     findSliceAtTs: function(ts) {
       if (!this.haveTopLevelSlicesBeenBuilt)
         throw new Error('Nope');
-      var i = tv.b.findIndexInSortedClosedIntervals(
+      var i = tr.b.findIndexInSortedClosedIntervals(
           this.topLevelSlices,
           getSliceLo, getSliceHi,
           ts);
@@ -309,7 +313,7 @@
 
       // Now recurse on slice looking for subSlice of given ts.
       while (true) {
-        var i = tv.b.findIndexInSortedClosedIntervals(
+        var i = tr.b.findIndexInSortedClosedIntervals(
             curSlice.subSlices,
             getSliceLo, getSliceHi,
             ts);
@@ -320,7 +324,7 @@
     },
 
     findNextSliceAfter: function(ts, refGuid) {
-      var i = tv.b.findLowIndexInSortedArray(
+      var i = tr.b.findLowIndexInSortedArray(
           this.slices, getSliceLo, ts);
       if (i === this.slices.length)
         return undefined;
@@ -344,8 +348,8 @@
     createSubSlices: function() {
       this.haveTopLevelSlicesBeenBuilt = true;
       this.createSubSlicesImpl_();
-      if (this.parentThread.timeSlices)
-        this.addCpuTimeToSubslices_(this.parentThread.timeSlices);
+      if (this.parentContainer.timeSlices)
+        this.addCpuTimeToSubslices_(this.parentContainer.timeSlices);
       this.slices.forEach(function(slice) {
         var selfTime = slice.duration;
         for (var i = 0; i < slice.subSlices.length; i++)
@@ -429,7 +433,7 @@
       this.slices = slices;
     },
     addCpuTimeToSubslices_: function(timeSlices) {
-      var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+      var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
       var sliceIdx = 0;
       timeSlices.forEach(function(timeSlice) {
         if (timeSlice.schedulingState == SCHEDULING_STATE.RUNNING) {
@@ -534,13 +538,13 @@
     if (groupB.openPartialSlices_.length > 0)
       throw new Error('groupB has open partial slices');
 
-    if (groupA.parentThread != groupB.parentThread)
+    if (groupA.parentContainer != groupB.parentContainer)
       throw new Error('Different parent threads. Cannot merge');
 
     if (groupA.sliceConstructor != groupB.sliceConstructor)
       throw new Error('Different slice constructors. Cannot merge');
 
-    var result = new SliceGroup(groupA.parentThread,
+    var result = new SliceGroup(groupA.parentContainer,
                                 groupA.sliceConstructor,
                                 groupA.name_);
 
diff --git a/trace-viewer/trace_viewer/core/trace_model/slice_group_test.html b/trace-viewer/trace_viewer/model/slice_group_test.html
similarity index 94%
rename from trace-viewer/trace_viewer/core/trace_model/slice_group_test.html
rename to trace-viewer/trace_viewer/model/slice_group_test.html
index 5cff9bd..8bb5861 100644
--- a/trace-viewer/trace_viewer/core/trace_model/slice_group_test.html
+++ b/trace-viewer/trace_viewer/model/slice_group_test.html
@@ -6,20 +6,20 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/slice_group.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/slice_group.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var Slice = tv.c.trace_model.Slice;
-  var SliceGroup = tv.c.trace_model.SliceGroup;
-  var newSlice = tv.c.test_utils.newSlice;
-  var newSliceEx = tv.c.test_utils.newSliceEx;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-  var newThreadSlice = tv.c.test_utils.newThreadSlice;
-
+tr.b.unittest.testSuite(function() {
+  var Slice = tr.model.Slice;
+  var SliceGroup = tr.model.SliceGroup;
+  var newSlice = tr.c.test_utils.newSlice;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+  var newThreadSlice = tr.c.test_utils.newThreadSlice;
+  var newModel = tr.c.test_utils.newModel;
 
   test('basicBeginEnd', function() {
     var group = new SliceGroup({});
@@ -693,7 +693,7 @@
   });
 
   test('sliceGroupStableId', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var process = model.getOrCreateProcess(123);
     var thread = process.getOrCreateThread(456);
     var group = new SliceGroup(thread);
@@ -736,8 +736,8 @@
   });
 
   test('computeCpuDurationNoOverlap', function() {
-    var model = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var model = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var process = model.getOrCreateProcess(123);
     var t = process.getOrCreateThread(456);
     t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
@@ -752,8 +752,8 @@
   });
 
   test('computeCpuDurationPartialOverlap', function() {
-    var model = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var model = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var process = model.getOrCreateProcess(123);
     var t = process.getOrCreateThread(456);
     t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
@@ -768,8 +768,8 @@
   });
 
   test('computeCpuDurationFullOverlap', function() {
-    var model = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var model = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var process = model.getOrCreateProcess(123);
     var t = process.getOrCreateThread(456);
     t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
@@ -784,8 +784,8 @@
   });
 
   test('computeCpuSelfDurationWithSubslices', function() {
-    var model = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var model = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var process = model.getOrCreateProcess(123);
     var t = process.getOrCreateThread(456);
     t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
@@ -805,8 +805,8 @@
   });
 
   test('computeCpuDurationSmallTimeslices', function() {
-    var model = new tv.c.TraceModel();
-    var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+    var model = new tr.Model();
+    var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
     var process = model.getOrCreateProcess(123);
     var t = process.getOrCreateThread(456);
     t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 1),
@@ -832,5 +832,20 @@
     assert.equal(group.slices[2].cpuDuration, 3);
     assert.equal(group.slices[2].cpuSelfTime, 3);
   });
+
+  test('sliceParentContainerSetAtPush', function() {
+    var m = newModel(function(m) {
+      m.process = m.getOrCreateProcess(123);
+      m.thread = m.process.getOrCreateThread(456);
+      m.group = new SliceGroup(m.thread);
+
+      m.sA = m.group.pushSlice(newSliceEx(
+          { title: 'sA', start: 0.0, duration: 10.0 }));
+
+      m.group.createSubSlices();
+    });
+
+    assert.deepEqual(m.sA.parentContainer, m.thread);
+  });
 });
 </script>
diff --git a/trace-viewer/trace_viewer/model/slice_test.html b/trace-viewer/trace_viewer/model/slice_test.html
new file mode 100644
index 0000000..62d0b3b
--- /dev/null
+++ b/trace-viewer/trace_viewer/model/slice_test.html
@@ -0,0 +1,140 @@
+<!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="import" href="/core/test_utils.html">
+<link rel="import" href="/model/slice_group.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  var Slice = tr.model.Slice;
+  var SliceGroup = tr.model.SliceGroup;
+  var newSlice = tr.c.test_utils.newSlice;
+  var newSliceEx = tr.c.test_utils.newSliceEx;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+
+  test('findDescendentSlice', function() {
+    var group = new SliceGroup({});
+
+    var sA = group.pushSlice(newSliceEx(
+        { title: 'sA', start: 0.0, duration: 10.0 }));
+    var sB = group.pushSlice(newSliceEx(
+        { title: 'sB', start: 0.0, duration: 4.0 }));
+    var sC = group.pushSlice(newSliceEx(
+        { title: 'sC', start: 0.0, duration: 2.0 }));
+
+    group.createSubSlices();
+
+    assert.deepEqual(sB, sA.findDescendentSlice('sB'));
+    assert.deepEqual(sC, sA.findDescendentSlice('sC'));
+    assert.isUndefined(sA.findDescendentSlice('sD'));
+  });
+
+  test('iterateAllDescendents', function() {
+    var group = new SliceGroup({});
+
+    var sA = group.pushSlice(newSliceEx(
+        { title: 'sA', start: 0.0, duration: 10.0 }));
+    var sB = group.pushSlice(newSliceEx(
+        { title: 'sB', start: 0.0, duration: 4.0 }));
+    var sC = group.pushSlice(newSliceEx(
+        { title: 'sC', start: 0.0, duration: 2.0 }));
+
+    group.createSubSlices();
+
+    assert.deepEqual(sA.descendentSlices, [sB, sC]);
+    assert.deepEqual(sC.descendentSlices, []);
+  });
+
+  test('mostTopLevelSlice', function() {
+    var group = new SliceGroup({});
+
+    var sA = group.pushSlice(newSliceEx(
+        { title: 'sA', start: 0.0, duration: 10.0 }));
+    var sB = group.pushSlice(newSliceEx(
+        { title: 'sB', start: 0.0, duration: 4.0 }));
+    var sC = group.pushSlice(newSliceEx(
+        { title: 'sC', start: 0.0, duration: 2.0 }));
+
+    group.createSubSlices();
+
+    assert.equal(sA.mostTopLevelSlice, sA);
+    assert.equal(sB.mostTopLevelSlice, sA);
+    assert.equal(sC.mostTopLevelSlice, sA);
+  });
+
+  test('iterateAllAncestors', function() {
+    var group = new SliceGroup({});
+
+    var sA = group.pushSlice(newSliceEx(
+        { title: 'sA', start: 0.0, duration: 10.0 }));
+    var sB = group.pushSlice(newSliceEx(
+        { title: 'sB', start: 0.0, duration: 4.0 }));
+    var sC = group.pushSlice(newSliceEx(
+        { title: 'sC', start: 0.0, duration: 2.0 }));
+
+    group.createSubSlices();
+
+    // Note that we iterate ancestors from the leaves to the root
+    assert.deepEqual(sC.ancestorSlices, [sB, sA]);
+    assert.deepEqual(sA.ancestorSlices, []);
+  });
+
+  test('iterateAllSubsequentSlices', function() {
+    var group = new SliceGroup({});
+
+    // [     A     ]
+    // [ B ][ D ][F]
+    // [C]  [E]
+
+    var sA = group.pushSlice(newSliceEx(
+        { title: 'sA', start: 0.0, duration: 10.0 }));
+    var sB = group.pushSlice(newSliceEx(
+        { title: 'sB', start: 0.0, duration: 4.0 }));
+    var sC = group.pushSlice(newSliceEx(
+        { title: 'sC', start: 0.0, duration: 2.0 }));
+    var sD = group.pushSlice(newSliceEx(
+        { title: 'sD', start: 5.0, duration: 2.0 }));
+    var sE = group.pushSlice(newSliceEx(
+        { title: 'sE', start: 5.0, duration: 1.0 }));
+    var sF = group.pushSlice(newSliceEx(
+        { title: 'sF', start: 8.0, duration: 2.0 }));
+
+    group.createSubSlices();
+
+    assert.deepEqual(sA.subsequentSlices, [sB, sC, sD, sE, sF]);
+    assert.deepEqual(sD.subsequentSlices, [sE, sF]);
+    assert.deepEqual(sF.subsequentSlices, []);
+  });
+
+  test('ancestorAndSubsequentSlices', function() {
+    var group = new SliceGroup({});
+
+    // [     A     ]
+    // [ B ][ D ][F]
+    // [C]  [E]
+
+    var sA = group.pushSlice(newSliceEx(
+        { title: 'sA', start: 0.0, duration: 10.0 }));
+    var sB = group.pushSlice(newSliceEx(
+        { title: 'sB', start: 0.0, duration: 4.0 }));
+    var sC = group.pushSlice(newSliceEx(
+        { title: 'sC', start: 0.0, duration: 2.0 }));
+    var sD = group.pushSlice(newSliceEx(
+        { title: 'sD', start: 5.0, duration: 2.0 }));
+    var sE = group.pushSlice(newSliceEx(
+        { title: 'sE', start: 5.0, duration: 1.0 }));
+    var sF = group.pushSlice(newSliceEx(
+        { title: 'sF', start: 8.0, duration: 2.0 }));
+
+    group.createSubSlices();
+
+    assert.deepEqual(sD.ancestorAndSubsequentSlices, [sD, sA, sE, sF]);
+  });
+});
+</script>
diff --git a/trace-viewer/trace_viewer/core/trace_model/stack_frame.html b/trace-viewer/trace_viewer/model/stack_frame.html
similarity index 97%
rename from trace-viewer/trace_viewer/core/trace_model/stack_frame.html
rename to trace-viewer/trace_viewer/model/stack_frame.html
index 40796d1..4ce554b 100644
--- a/trace-viewer/trace_viewer/core/trace_model/stack_frame.html
+++ b/trace-viewer/trace_viewer/model/stack_frame.html
@@ -8,7 +8,7 @@
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   function StackFrame(parentFrame, id, category, title, colorId) {
     if (id === undefined)
       throw new Error('id must be given');
diff --git a/trace-viewer/trace_viewer/core/trace_model/thread.html b/trace-viewer/trace_viewer/model/thread.html
similarity index 83%
rename from trace-viewer/trace_viewer/core/trace_model/thread.html
rename to trace-viewer/trace_viewer/model/thread.html
index 6f56083..5239e92 100644
--- a/trace-viewer/trace_viewer/core/trace_model/thread.html
+++ b/trace-viewer/trace_viewer/model/thread.html
@@ -5,10 +5,10 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/event_container.html">
-<link rel="import" href="/core/trace_model/thread_slice.html">
-<link rel="import" href="/core/trace_model/slice_group.html">
-<link rel="import" href="/core/trace_model/async_slice_group.html">
+<link rel="import" href="/model/event_container.html">
+<link rel="import" href="/model/thread_slice.html">
+<link rel="import" href="/model/slice_group.html">
+<link rel="import" href="/model/async_slice_group.html">
 <link rel="import" href="/base/guid.html">
 <link rel="import" href="/base/range.html">
 
@@ -18,13 +18,13 @@
 /**
  * @fileoverview Provides the Thread class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var Slice = tv.c.trace_model.Slice;
-  var SliceGroup = tv.c.trace_model.SliceGroup;
-  var AsyncSlice = tv.c.trace_model.AsyncSlice;
-  var AsyncSliceGroup = tv.c.trace_model.AsyncSliceGroup;
-  var ThreadSlice = tv.c.trace_model.ThreadSlice;
-  var ThreadTimeSlice = tv.c.trace_model.ThreadTimeSlice;
+tr.exportTo('tr.model', function() {
+  var Slice = tr.model.Slice;
+  var SliceGroup = tr.model.SliceGroup;
+  var AsyncSlice = tr.model.AsyncSlice;
+  var AsyncSliceGroup = tr.model.AsyncSliceGroup;
+  var ThreadSlice = tr.model.ThreadSlice;
+  var ThreadTimeSlice = tr.model.ThreadTimeSlice;
 
   /**
    * A Thread stores all the trace events collected for a particular
@@ -36,10 +36,10 @@
    * ThreadSlice.
    *
    * @constructor
-   * @extends {tv.c.trace_model.EventContainer}
+   * @extends {tr.model.EventContainer}
    */
   function Thread(parent, tid) {
-    this.guid_ = tv.b.GUID.allocate();
+    this.guid_ = tr.b.GUID.allocate();
     if (!parent)
       throw new Error('Parent must be provided.');
     this.parent = parent;
@@ -49,31 +49,18 @@
     this.samples_ = undefined; // Set during createSubSlices
 
     var that = this;
-    function ThreadSliceForThisThread(
-        cat, title, colorId, start, args, opt_duration,
-        opt_cpuStart, opt_cpuDuration) {
-      ThreadSlice.call(this, cat, title, colorId, start, args, opt_duration,
-                       opt_cpuStart, opt_cpuDuration);
-      this.parentThread = that;
-    }
-    ThreadSliceForThisThread.prototype = {
-      __proto__: ThreadSlice.prototype
-    };
 
-    this.sliceGroup = new SliceGroup(this, ThreadSliceForThisThread, 'slices');
+    this.sliceGroup = new SliceGroup(this, ThreadSlice, 'slices');
     this.timeSlices = undefined;
     this.kernelSliceGroup = new SliceGroup(
-        this, ThreadSliceForThisThread, 'kernel-slices');
+        this, ThreadSlice, 'kernel-slices');
     this.asyncSliceGroup = new AsyncSliceGroup(this, 'async-slices');
-    this.bounds = new tv.b.Range();
+    this.bounds = new tr.b.Range();
   }
 
   Thread.prototype = {
-    __proto__: tv.c.trace_model.EventContainer.prototype,
+    __proto__: tr.model.EventContainer.prototype,
 
-    /*
-     * @return {Number} A globally unique identifier for this counter.
-     */
     get guid() {
       return this.guid_;
     },
@@ -240,7 +227,7 @@
      * Returns the index of the slice in the timeSlices array, or undefined.
      */
     indexOfTimeSlice: function(timeSlice) {
-      var i = tv.b.findLowIndexInSortedArray(
+      var i = tr.b.findLowIndexInSortedArray(
           this.timeSlices,
           function(slice) { return slice.start; },
           timeSlice.start);
@@ -264,7 +251,7 @@
         stats[schedulingState] += overlapEnd - overlapStart;
       }
 
-      tv.b.iterateOverIntersectingIntervals(this.timeSlices,
+      tr.b.iterateOverIntersectingIntervals(this.timeSlices,
                                             function(x) { return x.start; },
                                             function(x) { return x.end; },
                                             start,
@@ -291,7 +278,7 @@
     if (tmp)
       return tmp;
 
-    tmp = tv.b.comparePossiblyUndefinedValues(
+    tmp = tr.b.comparePossiblyUndefinedValues(
         x.name, y.name,
         function(x, y) { return x.localeCompare(y); });
     if (tmp)
diff --git a/trace-viewer/trace_viewer/core/trace_model/thread_slice.html b/trace-viewer/trace_viewer/model/thread_slice.html
similarity index 81%
rename from trace-viewer/trace_viewer/core/trace_model/thread_slice.html
rename to trace-viewer/trace_viewer/model/thread_slice.html
index 15eaada..6e5f80c 100644
--- a/trace-viewer/trace_viewer/core/trace_model/thread_slice.html
+++ b/trace-viewer/trace_viewer/model/thread_slice.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/slice.html">
+<link rel="import" href="/model/slice.html">
 
 <script>
 'use strict';
@@ -13,8 +13,8 @@
 /**
  * @fileoverview Provides the Thread class.
  */
-tv.exportTo('tv.c.trace_model', function() {
-  var Slice = tv.c.trace_model.Slice;
+tr.exportTo('tr.model', function() {
+  var Slice = tr.model.Slice;
 
   /**
    * A ThreadSlice represents an interval of time on a thread resource
@@ -43,13 +43,13 @@
     __proto__: Slice.prototype
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       ThreadSlice,
       {
         name: 'slice',
         pluralName: 'slices',
-        singleViewElementName: 'tv-c-a-single-thread-slice-sub-view',
-        multiViewElementName: 'tv-c-a-multi-thread-slice-sub-view'
+        singleViewElementName: 'tr-c-a-single-thread-slice-sub-view',
+        multiViewElementName: 'tr-c-a-multi-thread-slice-sub-view'
       });
 
   return {
diff --git a/trace-viewer/trace_viewer/core/trace_model/thread_test.html b/trace-viewer/trace_viewer/model/thread_test.html
similarity index 83%
rename from trace-viewer/trace_viewer/core/trace_model/thread_test.html
rename to trace-viewer/trace_viewer/model/thread_test.html
index 66992c6..6d60e91 100644
--- a/trace-viewer/trace_viewer/core/trace_model/thread_test.html
+++ b/trace-viewer/trace_viewer/model/thread_test.html
@@ -6,22 +6,22 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
-  var ThreadSlice = tv.c.trace_model.ThreadSlice;
-  var Process = tv.c.trace_model.Process;
-  var Thread = tv.c.trace_model.Thread;
-  var newSliceNamed = tv.c.test_utils.newSliceNamed;
-  var newAsyncSlice = tv.c.test_utils.newAsyncSlice;
-  var newThreadSlice = tv.c.test_utils.newThreadSlice;
-  var SCHEDULING_STATE = tv.c.trace_model.SCHEDULING_STATE;
+tr.b.unittest.testSuite(function() {
+  var ThreadSlice = tr.model.ThreadSlice;
+  var Process = tr.model.Process;
+  var Thread = tr.model.Thread;
+  var newSliceNamed = tr.c.test_utils.newSliceNamed;
+  var newAsyncSlice = tr.c.test_utils.newAsyncSlice;
+  var newThreadSlice = tr.c.test_utils.newThreadSlice;
+  var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
 
   test('threadBounds_Empty', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t = new Thread(new Process(model, 7), 1);
     t.updateBounds();
     assert.isUndefined(t.bounds.min);
@@ -29,7 +29,7 @@
   });
 
   test('threadBounds_SubRow', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t = new Thread(new Process(model, 7), 1);
     t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
     t.updateBounds();
@@ -38,7 +38,7 @@
   });
 
   test('threadBounds_AsyncSliceGroup', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t = new Thread(new Process(model, 7), 1);
     t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
     t.asyncSliceGroup.push(newAsyncSlice(0.1, 5, t, t));
@@ -48,7 +48,7 @@
   });
 
   test('threadBounds_Cpu', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t = new Thread(new Process(model, 7), 1);
     t.timeSlices = [newSliceNamed('x', 0, 1)];
     t.updateBounds();
@@ -57,7 +57,7 @@
   });
 
   test('shiftTimestampsForwardWithCpu', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t = new Thread(new Process(model, 7), 1);
     t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 0, {}, 3));
     t.asyncSliceGroup.push(newAsyncSlice(0, 5, t, t));
@@ -77,7 +77,7 @@
   });
 
   test('shiftTimestampsForwardWithoutCpu', function() {
-    var model = new tv.c.TraceModel();
+    var model = new tr.Model();
     var t = new Thread(new Process(model, 7), 1);
     t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 0, {}, 3));
     t.asyncSliceGroup.push(newAsyncSlice(0, 5, t, t));
@@ -97,7 +97,7 @@
   test('getSchedulingStatsForRange', function() {
     var scheduledThread = undefined;
     var unscheduledThread = undefined;
-    var model = tv.c.test_utils.newModel(function(model) {
+    var model = tr.c.test_utils.newModel(function(model) {
       unscheduledThread = model.getOrCreateProcess(1).getOrCreateThread(1);
       unscheduledThread.sliceGroup.pushSlice(newSliceNamed('work', 0, 20));
 
diff --git a/trace-viewer/trace_viewer/core/trace_model/thread_time_slice.html b/trace-viewer/trace_viewer/model/thread_time_slice.html
similarity index 91%
rename from trace-viewer/trace_viewer/core/trace_model/thread_time_slice.html
rename to trace-viewer/trace_viewer/model/thread_time_slice.html
index 50198b4..82508d7 100644
--- a/trace-viewer/trace_viewer/core/trace_model/thread_time_slice.html
+++ b/trace-viewer/trace_viewer/model/thread_time_slice.html
@@ -6,13 +6,13 @@
 -->
 
 <link rel="import" href="/base/range.html">
-<link rel="import" href="/core/trace_model/slice.html">
+<link rel="import" href="/model/slice.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
-  var Slice = tv.c.trace_model.Slice;
+tr.exportTo('tr.model', function() {
+  var Slice = tr.model.Slice;
 
 
   var SCHEDULING_STATE = {
@@ -60,7 +60,7 @@
     __proto__: Slice.prototype,
 
     getColorForState_: function(state) {
-      var getColorIdForReservedName = tv.b.ui.getColorIdForReservedName;
+      var getColorIdForReservedName = tr.b.ui.getColorIdForReservedName;
       switch (state) {
         case SCHEDULING_STATE.RUNNABLE:
           return getColorIdForReservedName('thread_state_runnable');
@@ -86,7 +86,7 @@
     },
 
     get analysisTypeName() {
-      return 'tv.c.analysis.ThreadTimeSlice';
+      return 'tr.c.analysis.ThreadTimeSlice';
     },
 
     getAssociatedCpuSlice: function() {
@@ -134,13 +134,13 @@
     }
   };
 
-  tv.c.trace_model.EventRegistry.register(
+  tr.model.EventRegistry.register(
       ThreadTimeSlice,
       {
         name: 'threadTimeSlice',
         pluralName: 'threadTimeSlices',
-        singleViewElementName: 'tv-c-single-thread-time-slice-sub-view',
-        multiViewElementName: 'tv-c-a-multi-thread-time-slice-sub-view'
+        singleViewElementName: 'tr-c-a-single-thread-time-slice-sub-view',
+        multiViewElementName: 'tr-c-a-multi-thread-time-slice-sub-view'
       });
 
 
diff --git a/trace-viewer/trace_viewer/core/trace_model/time_to_object_instance_map.html b/trace-viewer/trace_viewer/model/time_to_object_instance_map.html
similarity index 97%
rename from trace-viewer/trace_viewer/core/trace_model/time_to_object_instance_map.html
rename to trace-viewer/trace_viewer/model/time_to_object_instance_map.html
index b0633ab..a0c8ecb 100644
--- a/trace-viewer/trace_viewer/core/trace_model/time_to_object_instance_map.html
+++ b/trace-viewer/trace_viewer/model/time_to_object_instance_map.html
@@ -13,7 +13,7 @@
 /**
  * @fileoverview Provides the TimeToObjectInstanceMap class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * Tracks all the instances associated with a given ID over its lifetime.
    *
@@ -57,7 +57,7 @@
             this.parent, this.id, category, name, ts, opt_baseTypeName));
       }
 
-      var i = tv.b.findIndexInSortedIntervals(
+      var i = tr.b.findIndexInSortedIntervals(
           this.instances,
           function(inst) { return inst.creationTs; },
           function(inst) { return inst.deletionTs - inst.creationTs; },
@@ -151,7 +151,7 @@
     },
 
     getInstanceAt: function(ts) {
-      var i = tv.b.findIndexInSortedIntervals(
+      var i = tr.b.findIndexInSortedIntervals(
           this.instances,
           function(inst) { return inst.creationTs; },
           function(inst) { return inst.deletionTs - inst.creationTs; },
diff --git a/trace-viewer/trace_viewer/core/trace_model/time_to_object_instance_map_test.html b/trace-viewer/trace_viewer/model/time_to_object_instance_map_test.html
similarity index 86%
rename from trace-viewer/trace_viewer/core/trace_model/time_to_object_instance_map_test.html
rename to trace-viewer/trace_viewer/model/time_to_object_instance_map_test.html
index 0ab0dbe..3dcab0d 100644
--- a/trace-viewer/trace_viewer/core/trace_model/time_to_object_instance_map_test.html
+++ b/trace-viewer/trace_viewer/model/time_to_object_instance_map_test.html
@@ -6,20 +6,20 @@
 -->
 
 <link rel="import" href="/core/test_utils.html">
-<link rel="import" href="/core/trace_model/time_to_object_instance_map.html">
-<link rel="import" href="/core/trace_model/object_instance.html">
+<link rel="import" href="/model/time_to_object_instance_map.html">
+<link rel="import" href="/model/object_instance.html">
 
 <script>
 'use strict';
 
-tv.b.unittest.testSuite(function() {
+tr.b.unittest.testSuite(function() {
   var createObjectInstance = function(parent, id, category, name, creationTs) {
-    return new tv.c.trace_model.ObjectInstance(
+    return new tr.model.ObjectInstance(
         parent, id, category, name, creationTs);
   };
 
   test('timeToObjectInstanceMap', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     m.addSnapshot('cat', 'name', 10, 'a1');
     m.addSnapshot('cat', 'name', 20, 'a2');
@@ -63,7 +63,7 @@
   });
 
   test('timeToObjectInstanceMapsBoundsLogic', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     m.addSnapshot('cat', 'name', 10, 'a1');
     m.addSnapshot('cat', 'name', 20, 'a2');
@@ -83,7 +83,7 @@
   });
 
   test('earlySnapshot', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     var i10 = m.idWasCreated('cat', 'name', 10, 'a1');
     m.idWasDeleted('cat', 'name', 20);
@@ -96,7 +96,7 @@
   });
 
   test('earlySnapshotWithImplicitCreate', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     var i10 = m.idWasDeleted('cat', 'name', 20);
     m.addSnapshot('cat', 'name', 5, 'a1');
@@ -105,7 +105,7 @@
   });
 
   test('getInstanceBeforeCreationImplicitCreate', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     var i10 = m.idWasCreated('cat', 'name', 10, 'a1');
     m.idWasDeleted('cat', 'name', 20);
@@ -113,7 +113,7 @@
   });
 
   test('getInstanceBeforeCreationImplicitCreateWithSnapshot', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     var s5 = m.addSnapshot('cat', 'name', 5, 'a1');
     var i10 = m.idWasDeleted('cat', 'name', 20);
@@ -121,7 +121,7 @@
   });
 
   test('successiveDeletions', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     var i20 = m.idWasDeleted('cat', 'name', 20);
     var i30 = m.idWasDeleted('cat', 'name', 30);
@@ -144,7 +144,7 @@
   });
 
   test('snapshotAfterDeletion', function() {
-    var m = new tv.c.trace_model.TimeToObjectInstanceMap(
+    var m = new tr.model.TimeToObjectInstanceMap(
         createObjectInstance, {}, 7);
     var i10 = m.idWasCreated('cat', 'name', 10, 'a1');
     m.idWasDeleted('cat', 'name', 20);
diff --git a/trace-viewer/trace_viewer/core/trace_model/timed_event.html b/trace-viewer/trace_viewer/model/timed_event.html
similarity index 88%
rename from trace-viewer/trace_viewer/core/trace_model/timed_event.html
rename to trace-viewer/trace_viewer/model/timed_event.html
index fd8ae2e..fd0e303 100644
--- a/trace-viewer/trace_viewer/core/trace_model/timed_event.html
+++ b/trace-viewer/trace_viewer/model/timed_event.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/event.html">
+<link rel="import" href="/model/event.html">
 <link rel="import" href="/base/guid.html">
 
 <script>
@@ -14,7 +14,7 @@
 /**
  * @fileoverview Provides the TimedEvent class.
  */
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
   /**
    * A TimedEvent is the base type for any piece of data in the trace model with
    * a specific start and duration.
@@ -22,7 +22,7 @@
    * @constructor
    */
   function TimedEvent(start) {
-    tv.c.trace_model.Event.call(this);
+    tr.model.Event.call(this);
     this.start = start;
     this.duration = 0;
     this.cpuStart = undefined;
@@ -30,7 +30,7 @@
   }
 
   TimedEvent.prototype = {
-    __proto__: tv.c.trace_model.Event.prototype,
+    __proto__: tr.model.Event.prototype,
 
     get end() {
       return this.start + this.duration;
diff --git a/trace-viewer/trace_viewer/core/trace_model/x_marker_annotation.html b/trace-viewer/trace_viewer/model/x_marker_annotation.html
similarity index 73%
rename from trace-viewer/trace_viewer/core/trace_model/x_marker_annotation.html
rename to trace-viewer/trace_viewer/model/x_marker_annotation.html
index 3143d8e..76094f6 100644
--- a/trace-viewer/trace_viewer/core/trace_model/x_marker_annotation.html
+++ b/trace-viewer/trace_viewer/model/x_marker_annotation.html
@@ -5,16 +5,16 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/core/trace_model/annotation.html">
+<link rel="import" href="/model/annotation.html">
 <link rel="import" href="/core/tracks/x_marker_annotation_view.html">
 
 <script>
 'use strict';
 
-tv.exportTo('tv.c.trace_model', function() {
+tr.exportTo('tr.model', function() {
 
   function XMarkerAnnotation(timestamp) {
-    tv.c.trace_model.Annotation.apply(this, arguments);
+    tr.model.Annotation.apply(this, arguments);
 
     this.timestamp = timestamp;
     this.strokeStyle = 'rgba(0, 0, 255, 0.5)';
@@ -25,7 +25,7 @@
   }
 
   XMarkerAnnotation.prototype = {
-    __proto__: tv.c.trace_model.Annotation.prototype,
+    __proto__: tr.model.Annotation.prototype,
 
     toDict: function() {
       return {
@@ -37,11 +37,11 @@
     },
 
     createView_: function(viewport) {
-      return new tv.c.annotations.XMarkerAnnotationView(viewport, this);
+      return new tr.c.annotations.XMarkerAnnotationView(viewport, this);
     }
   };
 
-  tv.c.trace_model.Annotation.register(
+  tr.model.Annotation.register(
       XMarkerAnnotation, {typeName: 'xmarker'});
 
   return {
diff --git a/trace-viewer/trace_viewer/trace_viewer.html b/trace-viewer/trace_viewer/trace_viewer.html
index b04de00..e64f832 100644
--- a/trace-viewer/trace_viewer/trace_viewer.html
+++ b/trace-viewer/trace_viewer/trace_viewer.html
@@ -7,25 +7,26 @@
 <link rel="stylesheet" href="/base/ui/common.css">
 <link rel="import" href="/base/ui.html">
 <link rel="import" href="/core/timeline_view.html">
-<link rel="import" href="/core/trace_model/trace_model.html">
+<link rel="import" href="/model/model.html">
+
 <script>
 'use strict';
-tv.exportTo('tv', function() {
+tr.exportTo('tr', function() {
   /**
    * Creates a trace viewer and, if given, loads the provided URL.
    *
-   * For more advanced usage, consider using TimelineView and TraceModel
+   * For more advanced usage, consider using TimelineView and Model
    * directly.
    *
    * Returns an HTMLElement that is the trace-viwer.
    */
-  var TraceViewer = tv.b.ui.define('trace-viewer', tv.c.TimelineView);
+  var TraceViewer = tr.b.ui.define('trace-viewer', tr.c.TimelineView);
 
   TraceViewer.prototype = {
-    __proto__: tv.c.TimelineView.prototype,
+    __proto__: tr.c.TimelineView.prototype,
 
     decorate: function(opt_url) {
-      tv.c.TimelineView.prototype.decorate.call(this);
+      tr.c.TimelineView.prototype.decorate.call(this);
 
       if (opt_url === undefined)
         return;
@@ -52,7 +53,7 @@
       req.send(null);
 
       function onResultFail(err) {
-        var overlay = new tv.b.ui.Overlay();
+        var overlay = new tr.b.ui.Overlay();
         overlay.textContent = err + ': ' + url + ' could not be loaded';
         overlay.title = 'Failed to fetch data';
         overlay.visible = true;
@@ -60,7 +61,7 @@
 
       var model;
       function onResult(result) {
-        model = new tv.c.TraceModel();
+        model = new tr.Model();
         var p = model.importTracesWithProgressDialog([result], true);
         p.then(onModelLoaded, onImportFail);
       }
@@ -73,8 +74,8 @@
       }
 
       function onImportFail() {
-        var overlay = new tv.b.ui.Overlay();
-        overlay.textContent = tv.b.normalizeException(err).message;
+        var overlay = new tr.b.ui.Overlay();
+        overlay.textContent = tr.b.normalizeException(err).message;
         overlay.title = 'Import error';
         overlay.visible = true;
       }
diff --git a/trace-viewer/trace_viewer/trace_viewer_project.py b/trace-viewer/trace_viewer/trace_viewer_project.py
index c9e9176..0fccd91 100644
--- a/trace-viewer/trace_viewer/trace_viewer_project.py
+++ b/trace-viewer/trace_viewer/trace_viewer_project.py
@@ -73,7 +73,6 @@
 
   def __init__(self, *args, **kwargs):
     super(TraceViewerProject, self).__init__(*args, **kwargs)
-
     self.source_paths.append(self.src_path)
     self.source_paths.append(self.trace_viewer_third_party_path)
     self.source_paths.append(self.jszip_path)