15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var g_browserBridge; 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var g_mainView; 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(eroman): The handling of "max" across snapshots is not correct. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For starters the browser needs to be aware to generate new maximums. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Secondly, we need to take into account the "max" of intermediary snapshots, 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not just the terminal ones. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Main entry point called once the page has loaded. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function onLoad() { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browserBridge = new BrowserBridge(); 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_mainView = new MainView(); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)document.addEventListener('DOMContentLoaded', onLoad); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This class provides a "bridge" for communicating between the javascript and 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the browser. Used as a singleton. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var BrowserBridge = (function() { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'use strict'; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function BrowserBridge() { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserBridge.prototype = { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) //-------------------------------------------------------------------------- 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Messages sent to the browser 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) //-------------------------------------------------------------------------- 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sendGetData: function() { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome.send('getData'); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sendResetData: function() { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome.send('resetData'); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) //-------------------------------------------------------------------------- 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Messages received from the browser. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) //-------------------------------------------------------------------------- 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receivedData: function(data) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(eroman): The browser should give an indication of which snapshot 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this data belongs to. For now we always assume it is for the latest. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_mainView.addDataToSnapshot(data); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BrowserBridge; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This class handles the presentation of our profiler view. Used as a 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * singleton. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var MainView = (function() { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'use strict'; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Important IDs in the HTML document 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The search box to filter results. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var FILTER_SEARCH_ID = 'filter-search'; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The container node to put all the "Group by" dropdowns into. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var GROUP_BY_CONTAINER_ID = 'group-by-container'; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The container node to put all the "Sort by" dropdowns into. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var SORT_BY_CONTAINER_ID = 'sort-by-container'; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The DIV to put all the tables into. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var RESULTS_DIV_ID = 'results-div'; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The container node to put all the column (visibility) checkboxes into. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var COLUMN_TOGGLES_CONTAINER_ID = 'column-toggles-container'; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The container node to put all the column (merge) checkboxes into. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var COLUMN_MERGE_TOGGLES_CONTAINER_ID = 'column-merge-toggles-container'; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The anchor which toggles visibility of column checkboxes. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var EDIT_COLUMNS_LINK_ID = 'edit-columns-link'; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The container node to show/hide when toggling the column checkboxes. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var EDIT_COLUMNS_ROW = 'edit-columns-row'; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The checkbox which controls whether things like "Worker Threads" and 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "PAC threads" will be merged together. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var MERGE_SIMILAR_THREADS_CHECKBOX_ID = 'merge-similar-threads-checkbox'; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var RESET_DATA_LINK_ID = 'reset-data-link'; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var TOGGLE_SNAPSHOTS_LINK_ID = 'snapshots-link'; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var SNAPSHOTS_ROW = 'snapshots-row'; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var SNAPSHOT_SELECTION_SUMMARY_ID = 'snapshot-selection-summary'; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var TAKE_SNAPSHOT_BUTTON_ID = 'take-snapshot-button'; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var SAVE_SNAPSHOTS_BUTTON_ID = 'save-snapshots-button'; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var SNAPSHOT_FILE_LOADER_ID = 'snapshot-file-loader'; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var LOAD_ERROR_ID = 'file-load-error'; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var DOWNLOAD_ANCHOR_ID = 'download-anchor'; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Row keys 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Each row of our data is an array of values rather than a dictionary. This 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avoids some overhead from repeating the key string multiple times, and 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // speeds up the property accesses a bit. The following keys are well-known 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // indexes into the array for various properties. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that the declaration order will also define the default display order. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var BEGIN_KEY = 1; // Start at 1 rather than 0 to simplify sorting code. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var END_KEY = BEGIN_KEY; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_COUNT = END_KEY++; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_RUN_TIME = END_KEY++; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_AVG_RUN_TIME = END_KEY++; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_MAX_RUN_TIME = END_KEY++; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_QUEUE_TIME = END_KEY++; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_AVG_QUEUE_TIME = END_KEY++; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_MAX_QUEUE_TIME = END_KEY++; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_BIRTH_THREAD = END_KEY++; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_DEATH_THREAD = END_KEY++; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_PROCESS_TYPE = END_KEY++; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_PROCESS_ID = END_KEY++; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_FUNCTION_NAME = END_KEY++; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_SOURCE_LOCATION = END_KEY++; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_FILE_NAME = END_KEY++; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_LINE_NUMBER = END_KEY++; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var NUM_KEYS = END_KEY - BEGIN_KEY; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Aggregators 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To generalize computing/displaying the aggregate "counts" for each column, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we specify an optional "Aggregator" class to use with each property. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The following are actually "Aggregator factories". They create an 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // aggregator instance by calling 'create()'. The instance is then fed 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // each row one at a time via the 'consume()' method. After all rows have 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // been consumed, the 'getValueAsText()' method will return the aggregated 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This aggregator counts the number of unique values that were fed to it. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var UniquifyAggregator = (function() { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function Aggregator(key) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.key_ = key; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.valuesSet_ = {}; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Aggregator.prototype = { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consume: function(e) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.valuesSet_[e[this.key_]] = true; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getValueAsText: function() { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return getDictionaryKeys(this.valuesSet_).length + ' unique'; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create: function(key) { return new Aggregator(key); } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) })(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This aggregator sums a numeric field. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var SumAggregator = (function() { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function Aggregator(key) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.key_ = key; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sum_ = 0; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Aggregator.prototype = { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consume: function(e) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sum_ += e[this.key_]; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getValue: function() { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.sum_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getValueAsText: function() { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return formatNumberAsText(this.getValue()); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create: function(key) { return new Aggregator(key); } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) })(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This aggregator computes an average by summing two 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * numeric fields, and then dividing the totals. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var AvgAggregator = (function() { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function Aggregator(numeratorKey, divisorKey) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.numeratorKey_ = numeratorKey; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.divisorKey_ = divisorKey; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.numeratorSum_ = 0; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.divisorSum_ = 0; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Aggregator.prototype = { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consume: function(e) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.numeratorSum_ += e[this.numeratorKey_]; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.divisorSum_ += e[this.divisorKey_]; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getValue: function() { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.numeratorSum_ / this.divisorSum_; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getValueAsText: function() { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return formatNumberAsText(this.getValue()); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create: function(numeratorKey, divisorKey) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create: function(key) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Aggregator(numeratorKey, divisorKey); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) })(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This aggregator finds the maximum for a numeric field. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var MaxAggregator = (function() { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function Aggregator(key) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.key_ = key; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.max_ = -Infinity; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Aggregator.prototype = { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consume: function(e) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.max_ = Math.max(this.max_, e[this.key_]); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getValue: function() { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.max_; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getValueAsText: function() { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return formatNumberAsText(this.getValue()); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create: function(key) { return new Aggregator(key); } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) })(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Key properties 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Custom comparator for thread names (sorts main thread and IO thread 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // higher than would happen lexicographically.) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var threadNameComparator = 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createLexicographicComparatorWithExceptions([ 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'CrBrowserMain', 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Chrome_IOThread', 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Chrome_FileThread', 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Chrome_HistoryThread', 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Chrome_DBThread', 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Still_Alive', 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ]); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function diffFuncForCount(a, b) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return b - a; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function diffFuncForMax(a, b) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return b; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Enumerates information about various keys. Such as whether their data is 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * expected to be numeric or is a string, a descriptive name (title) for the 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * property, and what function should be used to aggregate the property when 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * displayed in a column. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -------------------------------------- 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The following properties are required: 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -------------------------------------- 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [name]: This is displayed as the column's label. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [aggregator]: Aggregator factory that is used to compute an aggregate 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * value for this column. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -------------------------------------- 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The following properties are optional: 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -------------------------------------- 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [inputJsonKey]: The corresponding key for this property in the original 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * JSON dictionary received from the browser. If this is 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * present, values for this key will be automatically 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * populated during import. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [comparator]: A comparator function for sorting this column. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [textPrinter]: A function that transforms values into the user-displayed 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * text shown in the UI. If unspecified, will default to the 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "toString()" function. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [cellAlignment]: The horizonal alignment to use for columns of this 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * property (for instance 'right'). If unspecified will 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * default to left alignment. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [sortDescending]: When first clicking on this column, we will default to 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sorting by |comparator| in ascending order. If this 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * property is true, we will reverse that to descending. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [diff]: Function to call to compute a "difference" value between 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * parameters (a, b). This is used when calculating the difference 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * between two snapshots. Diffing numeric quantities generally 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * involves subtracting, but some fields like max may need to do 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * something different. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var KEY_PROPERTIES = []; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_PROCESS_ID] = { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'PID', 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_PROCESS_TYPE] = { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Process type', 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_BIRTH_THREAD] = { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Birth thread', 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'birth_thread', 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comparator: threadNameComparator, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_DEATH_THREAD] = { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Exec thread', 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'death_thread', 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comparator: threadNameComparator, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_FUNCTION_NAME] = { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Function name', 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'birth_location.function_name', 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_FILE_NAME] = { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'File name', 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'birth_location.file_name', 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_LINE_NUMBER] = { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Line number', 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'birth_location.line_number', 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_COUNT] = { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Count', 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortDescending: true, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) textPrinter: formatNumberAsText, 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'death_data.count', 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: SumAggregator, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff: diffFuncForCount, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_QUEUE_TIME] = { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Total queue time', 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortDescending: true, 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) textPrinter: formatNumberAsText, 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'death_data.queue_ms', 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: SumAggregator, 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff: diffFuncForCount, 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_MAX_QUEUE_TIME] = { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Max queue time', 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortDescending: true, 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) textPrinter: formatNumberAsText, 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'death_data.queue_ms_max', 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: MaxAggregator, 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff: diffFuncForMax, 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_RUN_TIME] = { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Total run time', 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortDescending: true, 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) textPrinter: formatNumberAsText, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'death_data.run_ms', 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: SumAggregator, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff: diffFuncForCount, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_AVG_RUN_TIME] = { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Avg run time', 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortDescending: true, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) textPrinter: formatNumberAsText, 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: AvgAggregator.create(KEY_RUN_TIME, KEY_COUNT), 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_MAX_RUN_TIME] = { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Max run time', 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortDescending: true, 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) textPrinter: formatNumberAsText, 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inputJsonKey: 'death_data.run_ms_max', 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: MaxAggregator, 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff: diffFuncForMax, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_AVG_QUEUE_TIME] = { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Avg queue time', 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cellAlignment: 'right', 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortDescending: true, 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) textPrinter: formatNumberAsText, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: AvgAggregator.create(KEY_QUEUE_TIME, KEY_COUNT), 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROPERTIES[KEY_SOURCE_LOCATION] = { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: 'Source location', 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type: 'string', 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregator: UniquifyAggregator, 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the string name for |key|. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getNameForKey(key) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var props = KEY_PROPERTIES[key]; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (props == undefined) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw 'Did not define properties for key: ' + key; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return props.name; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ordered list of all keys. This is the order we generally want 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to display the properties in. Default to declaration order. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ALL_KEYS = []; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var k = BEGIN_KEY; k < END_KEY; ++k) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ALL_KEYS.push(k); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default settings 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * List of keys for those properties which we want to initially omit 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * from the table. (They can be re-enabled by clicking [Edit columns]). 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var INITIALLY_HIDDEN_KEYS = [ 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_FILE_NAME, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_LINE_NUMBER, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_QUEUE_TIME, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ]; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The ordered list of grouping choices to expose in the "Group by" 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dropdowns. We don't include the numeric properties, since they 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * leads to awkward bucketing. 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var GROUPING_DROPDOWN_CHOICES = [ 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROCESS_TYPE, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROCESS_ID, 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_BIRTH_THREAD, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_DEATH_THREAD, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_FUNCTION_NAME, 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_SOURCE_LOCATION, 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_FILE_NAME, 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_LINE_NUMBER, 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ]; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The ordered list of sorting choices to expose in the "Sort by" 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dropdowns. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var SORT_DROPDOWN_CHOICES = ALL_KEYS; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The ordered list of all columns that can be displayed in the tables (not 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * including whatever has been hidden via [Edit Columns]). 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ALL_TABLE_COLUMNS = ALL_KEYS; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The initial keys to sort by when loading the page (can be changed later). 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var INITIAL_SORT_KEYS = [-KEY_COUNT]; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The default sort keys to use when nothing has been specified. 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var DEFAULT_SORT_KEYS = [-KEY_COUNT]; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The initial keys to group by when loading the page (can be changed later). 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var INITIAL_GROUP_KEYS = []; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The columns to give the option to merge on. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var MERGEABLE_KEYS = [ 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROCESS_ID, 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROCESS_TYPE, 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_BIRTH_THREAD, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_DEATH_THREAD, 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ]; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The columns to merge by default. 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var INITIALLY_MERGED_KEYS = []; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The full set of columns which define the "identity" for a row. A row is 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * considered equivalent to another row if it matches on all of these 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fields. This list is used when merging the data, to determine which rows 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * should be merged together. The remaining columns not listed in 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IDENTITY_KEYS will be aggregated. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var IDENTITY_KEYS = [ 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_BIRTH_THREAD, 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_DEATH_THREAD, 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROCESS_TYPE, 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_PROCESS_ID, 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_FUNCTION_NAME, 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_SOURCE_LOCATION, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_FILE_NAME, 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_LINE_NUMBER, 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ]; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The time (in milliseconds) to wait after receiving new data before 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * re-drawing it to the screen. The reason we wait a bit is to avoid 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * repainting repeatedly during the loading phase (which can slow things 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * down). Note that this only slows down the addition of new data. It does 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * not impact the latency of user-initiated operations like sorting or 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * merging. 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var PROCESS_DATA_DELAY_MS = 500; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The initial number of rows to display (the rest are hidden) when no 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * grouping is selected. We use a higher limit than when grouping is used 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * since there is a lot of vertical real estate. 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var INITIAL_UNGROUPED_ROW_LIMIT = 30; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The initial number of rows to display (rest are hidden) for each group. 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var INITIAL_GROUP_ROW_LIMIT = 10; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The number of extra rows to show/hide when clicking the "Show more" or 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "Show less" buttons. 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var LIMIT_INCREMENT = 10; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // General utility functions 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a list of all the keys in |dict|. 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getDictionaryKeys(dict) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var keys = []; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var key in dict) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keys.push(key); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return keys; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats the number |x| as a decimal integer. Strips off any decimal parts, 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and comma separates the number every 3 characters. 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function formatNumberAsText(x) { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var orig = x.toFixed(0); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parts = []; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var end = orig.length; end > 0; ) { 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var chunk = Math.min(end, 3); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts.push(orig.substr(end - chunk, chunk)); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end -= chunk; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return parts.reverse().join(','); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Simple comparator function which works for both strings and numbers. 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function simpleCompare(a, b) { 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a == b) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a < b) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a comparator function that compares values lexicographically, 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * but special-cases the values in |orderedList| to have a higher 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * rank. 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function createLexicographicComparatorWithExceptions(orderedList) { 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var valueToRankMap = {}; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < orderedList.length; ++i) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valueToRankMap[orderedList[i]] = i; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getCustomRank(x) { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rank = valueToRankMap[x]; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rank == undefined) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rank = Infinity; // Unmatched. 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rank; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function(a, b) { 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aRank = getCustomRank(a); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var bRank = getCustomRank(b); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not matched by any of our exceptions. 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (aRank == bRank) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return simpleCompare(a, b); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (aRank < bRank) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns dict[key]. Note that if |key| contains periods (.), they will be 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * interpreted as meaning a sub-property. 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getPropertyByPath(dict, key) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cur = dict; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parts = key.split('.'); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < parts.length; ++i) { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cur == undefined) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return undefined; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = cur[parts[i]]; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cur; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates and appends a DOM node of type |tagName| to |parent|. Optionally, 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sets the new node's text to |opt_text|. Returns the newly created node. 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function addNode(parent, tagName, opt_text) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var n = parent.ownerDocument.createElement(tagName); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent.appendChild(n); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_text != undefined) { 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(n, opt_text); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return n; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adds |text| to |parent|. 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function addText(parent, text) { 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var textNode = parent.ownerDocument.createTextNode(text); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent.appendChild(textNode); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return textNode; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Deletes all the strings in |array| which appear in |valuesToDelete|. 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function deleteValuesFromArray(array, valuesToDelete) { 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var valueSet = arrayToSet(valuesToDelete); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < array.length; ) { 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (valueSet[array[i]]) { 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) array.splice(i, 1); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Deletes all the repeated ocurrences of strings in |array|. 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function deleteDuplicateStringsFromArray(array) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build up set of each entry in array. 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var seenSoFar = {}; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < array.length; ) { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var value = array[i]; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (seenSoFar[value]) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) array.splice(i, 1); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) seenSoFar[value] = true; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Builds a map out of the array |list|. 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function arrayToSet(list) { 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var set = {}; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < list.length; ++i) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set[list[i]] = true; 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return set; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function trimWhitespace(text) { 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var m = /^\s*(.*)\s*$/.exec(text); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return m[1]; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Selects the option in |select| which has a value of |value|. 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function setSelectedOptionByValue(select, value) { 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < select.options.length; ++i) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select.options[i].value == value) { 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) select.options[i].selected = true; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adds a checkbox to |parent|. The checkbox will have a label on its right 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with text |label|. Returns the checkbox input node. 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function addLabeledCheckbox(parent, label) { 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var labelNode = addNode(parent, 'label'); 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var checkbox = addNode(labelNode, 'input'); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.type = 'checkbox'; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(labelNode, label); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return checkbox; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the last component in a path which is separated by either forward 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * slashes or backslashes. 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getFilenameFromPath(path) { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastSlash = Math.max(path.lastIndexOf('/'), 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.lastIndexOf('\\')); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lastSlash == -1) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path.substr(lastSlash + 1); 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the current time in milliseconds since unix epoch. 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getTimeMillis() { 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (new Date()).getTime(); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Toggle a node between hidden/invisible. 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function toggleNodeDisplay(n) { 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n.style.display == '') { 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n.style.display = 'none'; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n.style.display = ''; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Set the visibility state of a node. 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function setNodeDisplay(n, visible) { 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visible) { 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n.style.display = ''; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n.style.display = 'none'; 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Functions that augment, bucket, and compute aggregates for the input data. 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adds new derived properties to row. Mutates the provided dictionary |e|. 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function augmentDataRow(e) { 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computeDataRowAverages(e); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e[KEY_SOURCE_LOCATION] = e[KEY_FILE_NAME] + ' [' + e[KEY_LINE_NUMBER] + ']'; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function computeDataRowAverages(e) { 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e[KEY_AVG_QUEUE_TIME] = e[KEY_QUEUE_TIME] / e[KEY_COUNT]; 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e[KEY_AVG_RUN_TIME] = e[KEY_RUN_TIME] / e[KEY_COUNT]; 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates and initializes an aggregator object for each key in |columns|. 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns an array whose keys are values from |columns|, and whose 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * values are Aggregator instances. 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function initializeAggregates(columns) { 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregates = []; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < columns.length; ++i) { 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = columns[i]; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregatorFactory = KEY_PROPERTIES[key].aggregator; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregates[key] = aggregatorFactory.create(key); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return aggregates; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function consumeAggregates(aggregates, row) { 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var key in aggregates) 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregates[key].consume(row); 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function bucketIdenticalRows(rows, identityKeys, propertyGetterFunc) { 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var identicalRows = {}; 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < rows.length; ++i) { 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var r = rows[i]; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rowIdentity = []; 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var j = 0; j < identityKeys.length; ++j) 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rowIdentity.push(propertyGetterFunc(r, identityKeys[j])); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rowIdentity = rowIdentity.join('\n'); 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var l = identicalRows[rowIdentity]; 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!l) { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l = []; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identicalRows[rowIdentity] = l; 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l.push(r); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return identicalRows; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Merges the rows in |origRows|, by collapsing the columns listed in 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * |mergeKeys|. Returns an array with the merged rows (in no particular 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * order). 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If |mergeSimilarThreads| is true, then threads with a similar name will be 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * considered equivalent. For instance, "WorkerThread-1" and "WorkerThread-2" 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be remapped to "WorkerThread-*". 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If |outputAsDictionary| is false then the merged rows will be returned as a 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * flat list. Otherwise the result will be a dictionary, where each row 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * has a unique key. 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function mergeRows(origRows, mergeKeys, mergeSimilarThreads, 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputAsDictionary) { 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Define a translation function for each property. Normally we copy over 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // properties as-is, but if we have been asked to "merge similar threads" we 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we will remap the thread names that end in a numeric suffix. 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var propertyGetterFunc; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mergeSimilarThreads) { 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) propertyGetterFunc = function(row, key) { 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var value = row[key]; 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the property is a thread name, try to remap it. 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == KEY_BIRTH_THREAD || key == KEY_DEATH_THREAD) { 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var m = /^(.*[^\d])(\d+)$/.exec(value); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (m) 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = m[1] + '*'; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) propertyGetterFunc = function(row, key) { return row[key]; }; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine which sets of properties a row needs to match on to be 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // considered identical to another row. 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var identityKeys = IDENTITY_KEYS.slice(0); 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(identityKeys, mergeKeys); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set |aggregateKeys| to everything else, since we will be aggregating 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // their value as part of the merge. 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregateKeys = ALL_KEYS.slice(0); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(aggregateKeys, IDENTITY_KEYS); 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(aggregateKeys, mergeKeys); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Group all the identical rows together, bucketed into |identicalRows|. 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var identicalRows = 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucketIdenticalRows(origRows, identityKeys, propertyGetterFunc); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mergedRows = outputAsDictionary ? {} : []; 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Merge the rows and save the results to |mergedRows|. 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var k in identicalRows) { 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to smash the list |l| down to a single row... 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var l = identicalRows[k]; 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newRow = []; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (outputAsDictionary) { 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mergedRows[k] = newRow; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mergedRows.push(newRow); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy over all the identity columns to the new row (since they 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // were the same for each row matched). 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < identityKeys.length; ++i) 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[identityKeys[i]] = propertyGetterFunc(l[0], identityKeys[i]); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute aggregates for the other columns. 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregates = initializeAggregates(aggregateKeys); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Feed the rows to the aggregators. 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < l.length; ++i) 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumeAggregates(aggregates, l[i]); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Suck out the data generated by the aggregators. 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var aggregateKey in aggregates) 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[aggregateKey] = aggregates[aggregateKey].getValue(); 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mergedRows; 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Takes two dictionaries data1 and data2, and returns a new flat list which 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * represents the difference between them. The exact meaning of "difference" 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is column specific, but for most numeric fields (like the count, or total 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * time), it is found by subtracting. 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Rows in data1 and data2 are expected to use the same scheme for the keys. 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In other words, data1[k] is considered the analagous row to data2[k]. 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function subtractSnapshots(data1, data2, columnsToExclude) { 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These columns are computed from the other columns. We won't bother 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // diffing/aggregating these, but rather will derive them again from the 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // final row. 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var COMPUTED_AGGREGATE_KEYS = [KEY_AVG_QUEUE_TIME, KEY_AVG_RUN_TIME]; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These are the keys which determine row equality. Since we are not doing 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // any merging yet at this point, it is simply the list of all identity 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // columns. 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var identityKeys = IDENTITY_KEYS.slice(0); 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(identityKeys, columnsToExclude); 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The columns to compute via aggregation is everything else. 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregateKeys = ALL_KEYS.slice(0); 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(aggregateKeys, IDENTITY_KEYS); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(aggregateKeys, COMPUTED_AGGREGATE_KEYS); 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(aggregateKeys, columnsToExclude); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var diffedRows = []; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var rowId in data2) { 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var row1 = data1[rowId]; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var row2 = data2[rowId]; 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newRow = []; 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy over all the identity columns to the new row (since they 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // were the same for each row matched). 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < identityKeys.length; ++i) 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[identityKeys[i]] = row2[identityKeys[i]]; 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Diff the two rows. 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row1) { 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < aggregateKeys.length; ++i) { 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregateKey = aggregateKeys[i]; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var a = row1[aggregateKey]; 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var b = row2[aggregateKey]; 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var diffFunc = KEY_PROPERTIES[aggregateKey].diff; 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[aggregateKey] = diffFunc(a, b); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the the row doesn't appear in snapshot1, then there is nothing to 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // diff, so just copy row2 as is. 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < aggregateKeys.length; ++i) { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregateKey = aggregateKeys[i]; 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[aggregateKey] = row2[aggregateKey]; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newRow[KEY_COUNT] == 0) { 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a row's count has gone to zero, it means there were no new 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // occurrences of it in the second snapshot, so remove it. 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we excluded the averages during the diffing phase, re-compute 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them using the diffed totals. 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computeDataRowAverages(newRow); 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diffedRows.push(newRow); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return diffedRows; 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HTML drawing code 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getTextValueForProperty(key, value) { 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value == undefined) { 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A value may be undefined as a result of having merging rows. We 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // won't actually draw it, but this might be called by the filter. 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ''; 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var textPrinter = KEY_PROPERTIES[key].textPrinter; 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (textPrinter) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return textPrinter(value); 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value.toString(); 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Renders the property value |value| into cell |td|. The name of this 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * property is |key|. 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function drawValueToCell(td, key, value) { 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get a text representation of the value. 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var text = getTextValueForProperty(key, value); 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Apply the desired cell alignment. 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cellAlignment = KEY_PROPERTIES[key].cellAlignment; 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cellAlignment) 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) td.align = cellAlignment; 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == KEY_SOURCE_LOCATION) { 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Linkify the source column so it jumps to the source code. This doesn't 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // take into account the particular code this build was compiled from, or 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // local edits to source. It should however work correctly for top of tree 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // builds. 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var m = /^(.*) \[(\d+)\]$/.exec(text); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (m) { 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var filepath = m[1]; 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var filename = getFilenameFromPath(filepath); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var linenumber = m[2]; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var link = addNode(td, 'a', filename + ' [' + linenumber + ']'); 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://chromesrc.appspot.com is a server I wrote specifically for 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this task. It redirects to the appropriate source file; the file 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // paths given by the compiler can be pretty crazy and different 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between platforms. 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link.href = 'http://chromesrc.appspot.com/?path=' + 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encodeURIComponent(filepath) + '&line=' + linenumber; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link.target = '_blank'; 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // String values can get pretty long. If the string contains no spaces, then 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CSS fails to wrap it, and it overflows the cell causing the table to get 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // really big. We solve this using a hack: insert a <wbr> element after 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // every single character. This will allow the rendering engine to wrap the 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value, and hence avoid it overflowing! 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var kMinLengthBeforeWrap = 20; 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(td, text.substr(0, kMinLengthBeforeWrap)); 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = kMinLengthBeforeWrap; i < text.length; ++i) { 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(td, 'wbr'); 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(td, text.substr(i, 1)); 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helper code for handling the sort and grouping dropdowns. 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function addOptionsForGroupingSelect(select) { 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add "no group" choice. 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(select, 'option', '---').value = ''; 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < GROUPING_DROPDOWN_CHOICES.length; ++i) { 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = GROUPING_DROPDOWN_CHOICES[i]; 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var option = addNode(select, 'option', getNameForKey(key)); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) option.value = key; 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function addOptionsForSortingSelect(select) { 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add "no sort" choice. 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(select, 'option', '---').value = ''; 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a divider. 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(select, 'optgroup').label = ''; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < SORT_DROPDOWN_CHOICES.length; ++i) { 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = SORT_DROPDOWN_CHOICES[i]; 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(select, 'option', getNameForKey(key)).value = key; 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a divider. 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(select, 'optgroup').label = ''; 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the same options, but for descending. 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < SORT_DROPDOWN_CHOICES.length; ++i) { 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = SORT_DROPDOWN_CHOICES[i]; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var n = addNode(select, 'option', getNameForKey(key) + ' (DESC)'); 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n.value = reverseSortKey(key); 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Helper function used to update the sorting and grouping lists after a 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dropdown changes. 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function updateKeyListFromDropdown(list, i, select) { 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the list. 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < list.length) { 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list[i] = select.value; 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list.push(select.value); 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normalize the list, so setting 'none' as primary zeros out everything 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else. 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < list.length; ++i) { 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list[i] == '') { 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list.splice(i, list.length - i); 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Comparator for property |key|, having values |value1| and |value2|. 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the key has defined a custom comparator use it. Otherwise use a 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * default "less than" comparison. 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function compareValuesForKey(key, value1, value2) { 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var comparator = KEY_PROPERTIES[key].comparator; 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comparator) 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return comparator(value1, value2); 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return simpleCompare(value1, value2); 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function reverseSortKey(key) { 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -key; 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function sortKeyIsReversed(key) { 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return key < 0; 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function sortKeysMatch(key1, key2) { 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Math.abs(key1) == Math.abs(key2); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getKeysForCheckedBoxes(checkboxes) { 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var keys = []; 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var k in checkboxes) { 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (checkboxes[k].checked) 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keys.push(k); 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return keys; 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // -------------------------------------------------------------------------- 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function MainView() { 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we have a definition for each key. 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var k = BEGIN_KEY; k < END_KEY; ++k) { 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!KEY_PROPERTIES[k]) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw 'KEY_PROPERTIES[] not defined for key: ' + k; 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.init_(); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MainView.prototype = { 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addDataToSnapshot: function(data) { 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(eroman): We need to know which snapshot this data belongs to! 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now we assume it is the most recent snapshot. 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshotIndex = this.snapshots_.length - 1; 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshot = this.snapshots_[snapshotIndex]; 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var pid = data.process_id; 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ptype = data.process_type; 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the browser's representation of the data 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot.origData.push(data); 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Augment each data row with the process information. 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rows = data.list; 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < rows.length; ++i) { 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transform the data from a dictionary to an array. This internal 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // representation is more compact and faster to access. 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var origRow = rows[i]; 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newRow = []; 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[KEY_PROCESS_ID] = pid; 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[KEY_PROCESS_TYPE] = ptype; 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy over the known properties which have a 1:1 mapping with JSON. 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var k = BEGIN_KEY; k < END_KEY; ++k) { 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var inputJsonKey = KEY_PROPERTIES[k].inputJsonKey; 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inputJsonKey != undefined) { 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newRow[k] = getPropertyByPath(origRow, inputJsonKey); 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newRow[KEY_COUNT] == 0) { 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When resetting the data, it is possible for the backend to give us 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // counts of "0". There is no point adding these rows (in fact they 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will cause us to do divide by zeros when calculating averages and 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stuff), so we skip past them. 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add our computed properties. 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) augmentDataRow(newRow); 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot.flatData.push(newRow); 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!arrayToSet(this.getSelectedSnapshotIndexes_())[snapshotIndex]) { 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optimization: If this snapshot is not a data dependency for the 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current display, then don't bother updating anything. 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We may end up calling addDataToSnapshot_() repeatedly (once for each 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process). To avoid this from slowing us down we do bulk updates on a 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // timer. 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedDataSoon_(); 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateMergedDataSoon_: function() { 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.updateMergedDataPending_) { 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a delayed task has already been posted to re-merge the data, 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then we don't need to do anything extra. 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise schedule updateMergedData_() to be called later. We want it 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to be called no more than once every PROCESS_DATA_DELAY_MS 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // milliseconds. 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.lastUpdateMergedDataTime_ == undefined) 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastUpdateMergedDataTime_ = 0; 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var timeSinceLastMerge = getTimeMillis() - this.lastUpdateMergedDataTime_; 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var timeToWait = Math.max(0, PROCESS_DATA_DELAY_MS - timeSinceLastMerge); 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var functionToRun = function() { 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do the actual update. 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedData_(); 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep track of when we last ran. 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastUpdateMergedDataTime_ = getTimeMillis(); 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedDataPending_ = false; 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }.bind(this); 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedDataPending_ = true; 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.setTimeout(functionToRun, timeToWait); 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a list of the currently selected snapshots. This list is 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * guaranteed to be of length 1 or 2. 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getSelectedSnapshotIndexes_: function() { 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var indexes = this.getSelectedSnapshotBoxes_(); 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < indexes.length; ++i) 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) indexes[i] = indexes[i].__index; 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return indexes; 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Same as getSelectedSnapshotIndexes_(), only it returns the actual 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * checkbox input DOM nodes rather than the snapshot ID. 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getSelectedSnapshotBoxes_: function() { 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out which snaphots to use for our data. 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var boxes = []; 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.snapshots_.length; ++i) { 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var box = this.getSnapshotCheckbox_(i); 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (box.checked) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boxes.push(box); 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return boxes; 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Re-draw the description that explains which snapshots are currently 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * selected (if two snapshots were selected we explain that the *difference* 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * between them is being displayed). 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateSnapshotSelectionSummaryDiv_: function() { 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var summaryDiv = $(SNAPSHOT_SELECTION_SUMMARY_ID); 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var selectedSnapshots = this.getSelectedSnapshotIndexes_(); 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selectedSnapshots.length == 0) { 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This can occur during an attempt to load a file or following file 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // load failure. We just ignore it and move on. 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (selectedSnapshots.length == 1) { 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If only one snapshot is chosen then we will display that snapshot's 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data in its entirety. 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.flatData_ = this.snapshots_[selectedSnapshots[0]].flatData; 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't bother displaying any text when just 1 snapshot is selected, 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since it is obvious what this should do. 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) summaryDiv.innerText = ''; 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (selectedSnapshots.length == 2) { 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise if two snapshots were chosen, show the difference between 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them. 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshot1 = this.snapshots_[selectedSnapshots[0]]; 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshot2 = this.snapshots_[selectedSnapshots[1]]; 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var timeDeltaInSeconds = 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((snapshot2.time - snapshot1.time) / 1000).toFixed(0); 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Explain that what is being shown is the difference between two 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // snapshots. 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) summaryDiv.innerText = 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Showing the difference between snapshots #' + 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectedSnapshots[0] + ' and #' + 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectedSnapshots[1] + ' (' + timeDeltaInSeconds + 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' seconds worth of data)'; 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This shouldn't be possible... 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw 'Unexpected number of selected snapshots'; 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateMergedData_: function() { 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the merge options. 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mergeColumns = this.getMergeColumns_(); 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var shouldMergeSimilarThreads = this.shouldMergeSimilarThreads_(); 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var selectedSnapshots = this.getSelectedSnapshotIndexes_(); 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We do merges a bit differently depending if we are displaying the diffs 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between two snapshots, or just displaying a single snapshot. 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selectedSnapshots.length == 1) { 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshot = this.snapshots_[selectedSnapshots[0]]; 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergedData_ = mergeRows(snapshot.flatData, 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mergeColumns, 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shouldMergeSimilarThreads, 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (selectedSnapshots.length == 2) { 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshot1 = this.snapshots_[selectedSnapshots[0]]; 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshot2 = this.snapshots_[selectedSnapshots[1]]; 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Merge the data for snapshot1. 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mergedRows1 = mergeRows(snapshot1.flatData, 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mergeColumns, 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shouldMergeSimilarThreads, 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Merge the data for snapshot2. 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mergedRows2 = mergeRows(snapshot2.flatData, 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mergeColumns, 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shouldMergeSimilarThreads, 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do a diff between the two snapshots. 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergedData_ = subtractSnapshots(mergedRows1, 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mergedRows2, 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mergeColumns); 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw 'Unexpected number of selected snapshots'; 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Recompute filteredData_ (since it is derived from mergedData_) 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateFilteredData_(); 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateFilteredData_: function() { 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Recompute filteredData_. 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.filteredData_ = []; 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var filterFunc = this.getFilterFunction_(); 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.mergedData_.length; ++i) { 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var r = this.mergedData_[i]; 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!filterFunc(r)) { 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not matched by our filter, discard. 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.filteredData_.push(r); 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Recompute groupedData_ (since it is derived from filteredData_) 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateGroupedData_(); 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateGroupedData_: function() { 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Recompute groupedData_. 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupKeyToData = {}; 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var entryToGroupKeyFunc = this.getGroupingFunction_(); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.filteredData_.length; ++i) { 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var r = this.filteredData_[i]; 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupKey = entryToGroupKeyFunc(r); 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupData = groupKeyToData[groupKey]; 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!groupData) { 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupData = { 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key: JSON.parse(groupKey), 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aggregates: initializeAggregates(ALL_KEYS), 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rows: [], 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupKeyToData[groupKey] = groupData; 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the row to our list. 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupData.rows.push(r); 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update aggregates for each column. 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumeAggregates(groupData.aggregates, r); 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.groupedData_ = groupKeyToData; 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out a display order for the groups themselves. 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sortedGroupKeys_ = getDictionaryKeys(groupKeyToData); 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sortedGroupKeys_.sort(this.getGroupSortingFunction_()); 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sort the group data. 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sortGroupedData_(); 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortGroupedData_: function() { 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sortingFunc = this.getSortingFunction_(); 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var k in this.groupedData_) 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.groupedData_[k].rows.sort(sortingFunc); 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Every cached data dependency is now up to date, all that is left is 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to actually draw the result. 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redrawData_(); 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getVisibleColumnKeys_: function() { 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out what columns to include, based on the selected checkboxes. 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var columns = this.getSelectionColumns_(); 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) columns = columns.slice(0); 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Eliminate columns which we are merging on. 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(columns, this.getMergeColumns_()); 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Eliminate columns which we are grouped on. 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.sortedGroupKeys_.length > 0) { 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The grouping will be the the same for each so just pick the first. 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var randomGroupKey = this.groupedData_[this.sortedGroupKeys_[0]].key; 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The grouped properties are going to be the same for each row in our, 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // table, so avoid drawing them in our table! 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var keysToExclude = []; 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < randomGroupKey.length; ++i) 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keysToExclude.push(randomGroupKey[i].key); 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(columns, keysToExclude); 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are currently showing a "diff", hide the max columns, since we 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are not populating it correctly. See the TODO at the top of this file. 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.getSelectedSnapshotIndexes_().length > 1) 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(columns, [KEY_MAX_RUN_TIME, KEY_MAX_QUEUE_TIME]); 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return columns; 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redrawData_: function() { 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the results div, sine we may be overwriting older data. 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parent = $(RESULTS_DIV_ID); 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent.innerHTML = ''; 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var columns = this.getVisibleColumnKeys_(); 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw each group. 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.sortedGroupKeys_.length; ++i) { 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var k = this.sortedGroupKeys_[i]; 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.drawGroup_(parent, k, columns); 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Renders the information for a particular group. 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawGroup_: function(parent, groupKey, columns) { 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupData = this.groupedData_[groupKey]; 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var div = addNode(parent, 'div'); 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) div.className = 'group-container'; 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.drawGroupTitle_(div, groupData.key); 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var table = addNode(div, 'table'); 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.drawDataTable_(table, groupData, columns, groupKey); 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Draws a title into |parent| that describes |groupKey|. 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawGroupTitle_: function(parent, groupKey) { 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (groupKey.length == 0) { 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Empty group key means there was no grouping. 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parent = addNode(parent, 'div'); 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent.className = 'group-title-container'; 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Each component of the group key represents the "key=value" constraint 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for this group. Show these as an AND separated list. 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < groupKey.length; ++i) { 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i > 0) 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(parent, 'i', ' and '); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var e = groupKey[i]; 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(parent, 'b', getNameForKey(e.key) + ' = '); 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(parent, 'span', e.value); 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Renders a table which summarizes all |column| fields for |data|. 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawDataTable_: function(table, data, columns, groupKey) { 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) table.className = 'results-table'; 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var thead = addNode(table, 'thead'); 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tbody = addNode(table, 'tbody'); 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var displaySettings = this.getGroupDisplaySettings_(groupKey); 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var limit = displaySettings.limit; 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.drawAggregateRow_(thead, data.aggregates, columns); 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.drawTableHeader_(thead, columns); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.drawTableBody_(tbody, data.rows, columns, limit); 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.drawTruncationRow_(tbody, data.rows.length, limit, columns.length, 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupKey); 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawTableHeader_: function(thead, columns) { 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tr = addNode(thead, 'tr'); 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < columns.length; ++i) { 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = columns[i]; 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var th = addNode(tr, 'th', getNameForKey(key)); 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) th.onclick = this.onClickColumn_.bind(this, key); 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw an indicator if we are currently sorted on this column. 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(eroman): Should use an icon instead of asterisk! 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var j = 0; j < this.currentSortKeys_.length; ++j) { 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sortKeysMatch(this.currentSortKeys_[j], key)) { 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sortIndicator = addNode(th, 'span', '*'); 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortIndicator.style.color = 'red'; 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sortKeyIsReversed(this.currentSortKeys_[j])) { 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use double-asterisk for descending columns. 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(sortIndicator, '*'); 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawTableBody_: function(tbody, rows, columns, limit) { 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < rows.length && i < limit; ++i) { 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var e = rows[i]; 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tr = addNode(tbody, 'tr'); 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var c = 0; c < columns.length; ++c) { 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = columns[c]; 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var value = e[key]; 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var td = addNode(tr, 'td'); 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawValueToCell(td, key, value); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Renders a row that describes all the aggregate values for |columns|. 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawAggregateRow_: function(tbody, aggregates, columns) { 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tr = addNode(tbody, 'tr'); 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tr.className = 'aggregator-row'; 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < columns.length; ++i) { 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = columns[i]; 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var td = addNode(tr, 'td'); 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Most of our outputs are numeric, so we want to align them to the 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // right. However for the unique counts we will center. 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (KEY_PROPERTIES[key].aggregator == UniquifyAggregator) { 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) td.align = 'center'; 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) td.align = 'right'; 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var aggregator = aggregates[key]; 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (aggregator) 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) td.innerText = aggregator.getValueAsText(); 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Renders a row which describes how many rows the table has, how many are 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * currently hidden, and a set of buttons to show more. 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drawTruncationRow_: function(tbody, numRows, limit, numColumns, groupKey) { 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var numHiddenRows = Math.max(numRows - limit, 0); 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var numVisibleRows = numRows - numHiddenRows; 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tr = addNode(tbody, 'tr'); 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tr.className = 'truncation-row'; 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var td = addNode(tr, 'td'); 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) td.colSpan = numColumns; 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(td, numRows + ' rows'); 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (numHiddenRows > 0) { 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var s = addNode(td, 'span', ' (' + numHiddenRows + ' hidden) '); 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.style.color = 'red'; 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (numVisibleRows > LIMIT_INCREMENT) { 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(td, 'button', 'Show less').onclick = 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.changeGroupDisplayLimit_.bind( 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, groupKey, -LIMIT_INCREMENT); 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (numVisibleRows > 0) { 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(td, 'button', 'Show none').onclick = 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.changeGroupDisplayLimit_.bind(this, groupKey, -Infinity); 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (numHiddenRows > 0) { 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(td, 'button', 'Show more').onclick = 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.changeGroupDisplayLimit_.bind(this, groupKey, LIMIT_INCREMENT); 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(td, 'button', 'Show all').onclick = 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.changeGroupDisplayLimit_.bind(this, groupKey, Infinity); 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adjusts the row limit for group |groupKey| by |delta|. 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changeGroupDisplayLimit_: function(groupKey, delta) { 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the current settings for this group. 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var settings = this.getGroupDisplaySettings_(groupKey, true); 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute the adjusted limit. 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newLimit = settings.limit; 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var totalNumRows = this.groupedData_[groupKey].rows.length; 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLimit = Math.min(totalNumRows, newLimit); 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLimit += delta; 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLimit = Math.max(0, newLimit); 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the settings with the new limit. 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings.limit = newLimit; 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(eroman): It isn't necessary to redraw *all* the data. Really we 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just need to insert the missing rows (everything else stays the same)! 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redrawData_(); 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the rendering settings for group |groupKey|. This includes things 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * like how many rows to display in the table. 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getGroupDisplaySettings_: function(groupKey, opt_create) { 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var settings = this.groupDisplaySettings_[groupKey]; 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!settings) { 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have any settings for this group yet, create some 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default ones. 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (groupKey == '[]') { 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (groupKey of '[]' is what we use for ungrouped data). 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings = {limit: INITIAL_UNGROUPED_ROW_LIMIT}; 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings = {limit: INITIAL_GROUP_ROW_LIMIT}; 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_create) 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.groupDisplaySettings_[groupKey] = settings; 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return settings; 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) init_: function() { 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.snapshots_ = []; 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start fetching the data from the browser; this will be our snapshot #0. 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.takeSnapshot_(); 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Data goes through the following pipeline: 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (1) Raw data received from browser, and transformed into our own 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // internal row format (where properties are indexed by KEY_* 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // constants.) 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (2) We "augment" each row by adding some extra computed columns 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (like averages). 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (3) The rows are merged using current merge settings. 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (4) The rows that don't match current search expression are 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tossed out. 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (5) The rows are organized into "groups" based on current settings, 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and aggregate values are computed for each resulting group. 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (6) The rows within each group are sorted using current settings. 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (7) The grouped rows are drawn to the screen. 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergedData_ = []; 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.filteredData_ = []; 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.groupedData_ = {}; 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sortedGroupKeys_ = []; 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.groupDisplaySettings_ = {}; 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fillSelectionCheckboxes_($(COLUMN_TOGGLES_CONTAINER_ID)); 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fillMergeCheckboxes_($(COLUMN_MERGE_TOGGLES_CONTAINER_ID)); 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(FILTER_SEARCH_ID).onsearch = this.onChangedFilter_.bind(this); 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentSortKeys_ = INITIAL_SORT_KEYS.slice(0); 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentGroupingKeys_ = INITIAL_GROUP_KEYS.slice(0); 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fillGroupingDropdowns_(); 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fillSortingDropdowns_(); 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(EDIT_COLUMNS_LINK_ID).onclick = 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toggleNodeDisplay.bind(null, $(EDIT_COLUMNS_ROW)); 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(TOGGLE_SNAPSHOTS_LINK_ID).onclick = 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toggleNodeDisplay.bind(null, $(SNAPSHOTS_ROW)); 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).onchange = 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onMergeSimilarThreadsCheckboxChanged_.bind(this); 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(RESET_DATA_LINK_ID).onclick = 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browserBridge.sendResetData.bind(g_browserBridge); 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(TAKE_SNAPSHOT_BUTTON_ID).onclick = this.takeSnapshot_.bind(this); 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(SAVE_SNAPSHOTS_BUTTON_ID).onclick = this.saveSnapshots_.bind(this); 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(SNAPSHOT_FILE_LOADER_ID).onchange = this.loadFileChanged_.bind(this); 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) takeSnapshot_: function() { 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a new empty snapshot. Make note of the current time, so we know 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when the snaphot was taken. 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.snapshots_.push({flatData: [], origData: [], time: getTimeMillis()}); 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the UI to reflect the new snapshot. 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addSnapshotToList_(this.snapshots_.length - 1); 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask the browser for the profiling data. We will receive the data 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // later through a callback to addDataToSnapshot_(). 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browserBridge.sendGetData(); 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saveSnapshots_: function() { 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshots = []; 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.snapshots_.length; ++i) { 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshots.push({ data: this.snapshots_[i].origData, 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timestamp: Math.floor( 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.snapshots_[i].time / 1000) }); 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dump = { 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'userAgent': navigator.userAgent, 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'version': 1, 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'snapshots': snapshots 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dumpText = JSON.stringify(dump, null, ' '); 18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var textBlob = new Blob([dumpText], 18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { type: 'octet/stream', endings: 'native' }); 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var blobUrl = window.webkitURL.createObjectURL(textBlob); 18052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) $(DOWNLOAD_ANCHOR_ID).href = blobUrl; 18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) $(DOWNLOAD_ANCHOR_ID).click(); 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loadFileChanged_: function() { 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.loadSnapshots_($(SNAPSHOT_FILE_LOADER_ID).files[0]); 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loadSnapshots_: function(file) { 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file) { 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fileReader = new FileReader(); 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileReader.onload = this.onLoadSnapshotsFile_.bind(this, file); 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileReader.onerror = this.onLoadSnapshotsFileError_.bind(this, file); 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileReader.readAsText(file); 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onLoadSnapshotsFile_: function(file, event) { 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parsed = null; 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parsed = JSON.parse(event.target.result); 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed.version != 1) { 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new Error('Unrecognized version: ' + parsed.version); 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed.snapshots.length < 1) { 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new Error('File contains no data'); 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.displayLoadedFile_(file, parsed); 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.hideFileLoadError_(); 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (error) { 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.displayFileLoadError_('File load failure: ' + error.message); 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearExistingSnapshots_: function() { 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tbody = $('snapshots-tbody'); 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.snapshots_ = []; 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tbody.innerHTML = ''; 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedDataSoon_(); 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) displayLoadedFile_: function(file, content) { 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.clearExistingSnapshots_(); 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(TAKE_SNAPSHOT_BUTTON_ID).disabled = true; 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(SAVE_SNAPSHOTS_BUTTON_ID).disabled = true; 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content.snapshots.length > 1) { 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setNodeDisplay($(SNAPSHOTS_ROW), true); 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < content.snapshots.length; ++i) { 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshot = content.snapshots[i]; 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.snapshots_.push({flatData: [], origData: [], 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time: snapshot.timestamp * 1000}); 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addSnapshotToList_(this.snapshots_.length - 1); 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var snapshotData = snapshot.data; 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var j = 0; j < snapshotData.length; ++j) { 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addDataToSnapshot(snapshotData[j]); 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redrawData_(); 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onLoadSnapshotsFileError_: function(file, filedata) { 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.displayFileLoadError_('Error loading ' + file.name); 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) displayFileLoadError_: function(message) { 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(LOAD_ERROR_ID).textContent = message; 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(LOAD_ERROR_ID).hidden = false; 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hideFileLoadError_: function() { 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(LOAD_ERROR_ID).textContent = ''; 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $(LOAD_ERROR_ID).hidden = true; 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getSnapshotCheckbox_: function(i) { 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return $(this.getSnapshotCheckboxId_(i)); 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getSnapshotCheckboxId_: function(i) { 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'snapshotCheckbox-' + i; 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addSnapshotToList_: function(i) { 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tbody = $('snapshots-tbody'); 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tr = addNode(tbody, 'tr'); 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var id = this.getSnapshotCheckboxId_(i); 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var checkboxCell = addNode(tr, 'td'); 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var checkbox = addNode(checkboxCell, 'input'); 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.type = 'checkbox'; 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.id = id; 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.__index = i; 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.onclick = this.onSnapshotCheckboxChanged_.bind(this); 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addNode(tr, 'td', '#' + i); 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var labelCell = addNode(tr, 'td'); 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var l = addNode(labelCell, 'label'); 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dateString = new Date(this.snapshots_[i].time).toLocaleString(); 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(l, dateString); 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l.htmlFor = id; 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are on snapshot 0, make it the default. 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == 0) { 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.checked = true; 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.__time = getTimeMillis(); 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateSnapshotCheckboxStyling_(); 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateSnapshotCheckboxStyling_: function() { 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.snapshots_.length; ++i) { 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var checkbox = this.getSnapshotCheckbox_(i); 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.parentNode.parentNode.className = 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.checked ? 'selected_snapshot' : ''; 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onSnapshotCheckboxChanged_: function(event) { 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep track of when we clicked this box (for when we need to uncheck 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // older boxes). 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.target.__time = getTimeMillis(); 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find all the checked boxes. Either 1 or 2 can be checked. If a third 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was just checked, then uncheck one of the earlier ones so we only have 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var checked = this.getSelectedSnapshotBoxes_(); 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checked.sort(function(a, b) { return b.__time - a.__time; }); 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (checked.length > 2) { 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 2; i < checked.length; ++i) 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checked[i].checked = false; 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checked.length = 2; 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should always have at least 1 selection. Prevent the user from 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unselecting the final box. 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (checked.length == 0) 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.target.checked = true; 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateSnapshotCheckboxStyling_(); 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateSnapshotSelectionSummaryDiv_(); 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Recompute mergedData_ (since it is derived from selected snapshots). 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedData_(); 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fillSelectionCheckboxes_: function(parent) { 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionCheckboxes_ = {}; 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var onChangeFunc = this.onSelectCheckboxChanged_.bind(this); 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < ALL_TABLE_COLUMNS.length; ++i) { 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = ALL_TABLE_COLUMNS[i]; 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var checkbox = addLabeledCheckbox(parent, getNameForKey(key)); 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.checked = true; 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.onchange = onChangeFunc; 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(parent, ' '); 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionCheckboxes_[key] = checkbox; 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < INITIALLY_HIDDEN_KEYS.length; ++i) { 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionCheckboxes_[INITIALLY_HIDDEN_KEYS[i]].checked = false; 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getSelectionColumns_: function() { 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return getKeysForCheckedBoxes(this.selectionCheckboxes_); 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getMergeColumns_: function() { 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return getKeysForCheckedBoxes(this.mergeCheckboxes_); 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shouldMergeSimilarThreads_: function() { 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).checked; 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fillMergeCheckboxes_: function(parent) { 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergeCheckboxes_ = {}; 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var onChangeFunc = this.onMergeCheckboxChanged_.bind(this); 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < MERGEABLE_KEYS.length; ++i) { 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = MERGEABLE_KEYS[i]; 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var checkbox = addLabeledCheckbox(parent, getNameForKey(key)); 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkbox.onchange = onChangeFunc; 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addText(parent, ' '); 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergeCheckboxes_[key] = checkbox; 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < INITIALLY_MERGED_KEYS.length; ++i) { 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergeCheckboxes_[INITIALLY_MERGED_KEYS[i]].checked = true; 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fillGroupingDropdowns_: function() { 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parent = $(GROUP_BY_CONTAINER_ID); 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent.innerHTML = ''; 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i <= this.currentGroupingKeys_.length; ++i) { 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a dropdown. 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var select = addNode(parent, 'select'); 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) select.onchange = this.onChangedGrouping_.bind(this, select, i); 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addOptionsForGroupingSelect(select); 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < this.currentGroupingKeys_.length) { 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = this.currentGroupingKeys_[i]; 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setSelectedOptionByValue(select, key); 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fillSortingDropdowns_: function() { 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parent = $(SORT_BY_CONTAINER_ID); 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent.innerHTML = ''; 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i <= this.currentSortKeys_.length; ++i) { 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a dropdown. 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var select = addNode(parent, 'select'); 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) select.onchange = this.onChangedSorting_.bind(this, select, i); 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addOptionsForSortingSelect(select); 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < this.currentSortKeys_.length) { 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = this.currentSortKeys_[i]; 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setSelectedOptionByValue(select, key); 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onChangedGrouping_: function(select, i) { 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateKeyListFromDropdown(this.currentGroupingKeys_, i, select); 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fillGroupingDropdowns_(); 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateGroupedData_(); 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onChangedSorting_: function(select, i) { 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateKeyListFromDropdown(this.currentSortKeys_, i, select); 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fillSortingDropdowns_(); 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sortGroupedData_(); 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onSelectCheckboxChanged_: function() { 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redrawData_(); 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onMergeCheckboxChanged_: function() { 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedData_(); 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onMergeSimilarThreadsCheckboxChanged_: function() { 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateMergedData_(); 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onChangedFilter_: function() { 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateFilteredData_(); 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When left-clicking a column, change the primary sort order to that 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * column. If we were already sorted on that column then reverse the order. 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When alt-clicking, add a secondary sort column. Similarly, if 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * alt-clicking a column which was already being sorted on, reverse its 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * order. 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onClickColumn_: function(key, event) { 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this property wants to start off in descending order rather then 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ascending, flip it. 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (KEY_PROPERTIES[key].sortDescending) 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = reverseSortKey(key); 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scan through our sort order and see if we are already sorted on this 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // key. If so, reverse that sort ordering. 20912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var foundIndex = -1; 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.currentSortKeys_.length; ++i) { 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var curKey = this.currentSortKeys_[i]; 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sortKeysMatch(curKey, key)) { 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentSortKeys_[i] = reverseSortKey(curKey); 20962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) foundIndex = i; 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.altKey) { 21022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (foundIndex == -1) { 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we weren't already sorted on the column that was alt-clicked, 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then add it to our sort. 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentSortKeys_.push(key); 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 21082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (foundIndex != 0 || 21092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !sortKeysMatch(this.currentSortKeys_[foundIndex], key)) { 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the column we left-clicked wasn't already our primary column, 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make it so. 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentSortKeys_ = [key]; 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the column we left-clicked was already our primary column (and 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we just reversed it), remove any secondary sorts. 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentSortKeys_.length = 1; 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fillSortingDropdowns_(); 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.sortGroupedData_(); 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getSortingFunction_: function() { 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sortKeys = this.currentSortKeys_.slice(0); 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Eliminate the empty string keys (which means they were unspecified). 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(sortKeys, ['']); 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no sort is specified, use our default sort. 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sortKeys.length == 0) 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sortKeys = [DEFAULT_SORT_KEYS]; 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function(a, b) { 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < sortKeys.length; ++i) { 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var key = Math.abs(sortKeys[i]); 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var factor = sortKeys[i] < 0 ? -1 : 1; 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var propA = a[key]; 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var propB = b[key]; 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var comparison = compareValuesForKey(key, propA, propB); 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comparison *= factor; // Possibly reverse the ordering. 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comparison != 0) 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return comparison; 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tie breaker. 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return simpleCompare(JSON.stringify(a), JSON.stringify(b)); 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getGroupSortingFunction_: function() { 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function(a, b) { 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupKey1 = JSON.parse(a); 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupKey2 = JSON.parse(b); 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < groupKey1.length; ++i) { 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var comparison = compareValuesForKey( 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupKey1[i].key, 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupKey1[i].value, 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupKey2[i].value); 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comparison != 0) 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return comparison; 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tie breaker. 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return simpleCompare(a, b); 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getFilterFunction_: function() { 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var searchStr = $(FILTER_SEARCH_ID).value; 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normalize the search expression. 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) searchStr = trimWhitespace(searchStr); 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) searchStr = searchStr.toLowerCase(); 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function(x) { 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Match everything when there was no filter. 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (searchStr == '') 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Treat the search text as a LOWERCASE substring search. 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var k = BEGIN_KEY; k < END_KEY; ++k) { 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var propertyText = getTextValueForProperty(k, x[k]); 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (propertyText.toLowerCase().indexOf(searchStr) != -1) 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getGroupingFunction_: function() { 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupings = this.currentGroupingKeys_.slice(0); 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Eliminate the empty string groupings (which means they were 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unspecified). 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteValuesFromArray(groupings, ['']); 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Eliminate duplicate primary/secondary group by directives, since they 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are redundant. 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleteDuplicateStringsFromArray(groupings); 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function(e) { 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var groupKey = []; 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < groupings.length; ++i) { 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var entry = {key: groupings[i], 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value: e[groupings[i]]}; 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groupKey.push(entry); 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return JSON.stringify(groupKey); 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MainView; 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})(); 2224