OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 var g_browserBridge; | 5 var g_browserBridge; |
6 var g_mainView; | 6 var g_mainView; |
7 | 7 |
8 /** | 8 /** |
9 * Main entry point called once the page has loaded. | 9 * Main entry point called once the page has loaded. |
10 */ | 10 */ |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 /** | 534 /** |
535 * The time (in milliseconds) to wait after receiving new data before | 535 * The time (in milliseconds) to wait after receiving new data before |
536 * re-drawing it to the screen. The reason we wait a bit is to avoid | 536 * re-drawing it to the screen. The reason we wait a bit is to avoid |
537 * repainting repeatedly during the loading phase (which can slow things | 537 * repainting repeatedly during the loading phase (which can slow things |
538 * down). Note that this only slows down the addition of new data. It does | 538 * down). Note that this only slows down the addition of new data. It does |
539 * not impact the latency of user-initiated operations like sorting or | 539 * not impact the latency of user-initiated operations like sorting or |
540 * merging. | 540 * merging. |
541 */ | 541 */ |
542 var PROCESS_DATA_DELAY_MS = 500; | 542 var PROCESS_DATA_DELAY_MS = 500; |
543 | 543 |
| 544 /** |
| 545 * The initial number of rows to display (the rest are hidden) when no |
| 546 * grouping is selected. We use a higher limit than when grouping is used |
| 547 * since there is a lot of vertical real estate. |
| 548 */ |
| 549 var INITIAL_UNGROUPED_ROW_LIMIT = 30; |
| 550 |
| 551 /** |
| 552 * The initial number of rows to display (rest are hidden) for each group. |
| 553 */ |
| 554 var INITIAL_GROUP_ROW_LIMIT = 10; |
| 555 |
| 556 /** |
| 557 * The number of extra rows to show/hide when clicking the "Show more" or |
| 558 * "Show less" buttons. |
| 559 */ |
| 560 var LIMIT_INCREMENT = 10; |
| 561 |
544 // -------------------------------------------------------------------------- | 562 // -------------------------------------------------------------------------- |
545 // General utility functions | 563 // General utility functions |
546 // -------------------------------------------------------------------------- | 564 // -------------------------------------------------------------------------- |
547 | 565 |
548 /** | 566 /** |
549 * Returns a list of all the keys in |dict|. | 567 * Returns a list of all the keys in |dict|. |
550 */ | 568 */ |
551 function getDictionaryKeys(dict) { | 569 function getDictionaryKeys(dict) { |
552 var keys = []; | 570 var keys = []; |
553 for (var key in dict) { | 571 for (var key in dict) { |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 var e = groupKey[i]; | 896 var e = groupKey[i]; |
879 addNode(parent, 'b', getNameForKey(e.key) + ' = '); | 897 addNode(parent, 'b', getNameForKey(e.key) + ' = '); |
880 addNode(parent, 'span', e.value); | 898 addNode(parent, 'span', e.value); |
881 } | 899 } |
882 } | 900 } |
883 | 901 |
884 /** | 902 /** |
885 * Renders the information for a particular group. | 903 * Renders the information for a particular group. |
886 */ | 904 */ |
887 function drawGroup(parent, groupData, columns, | 905 function drawGroup(parent, groupData, columns, |
888 columnOnClickHandler, currentSortKeys) { | 906 columnOnClickHandler, currentSortKeys, displaySettings, |
| 907 expandHandler, shrinkHandler, showAllHandler, |
| 908 showNoneHandler) { |
889 var div = addNode(parent, 'div'); | 909 var div = addNode(parent, 'div'); |
890 div.className = 'group-container'; | 910 div.className = 'group-container'; |
891 | 911 |
892 drawGroupTitle(div, groupData.key); | 912 drawGroupTitle(div, groupData.key); |
893 | 913 |
894 var table = addNode(div, 'table'); | 914 var table = addNode(div, 'table'); |
895 | 915 |
896 drawDataTable(table, groupData, columns, columnOnClickHandler, | 916 drawDataTable(table, groupData, columns, columnOnClickHandler, |
897 currentSortKeys); | 917 currentSortKeys, displaySettings.limit, |
| 918 expandHandler, shrinkHandler, showAllHandler, |
| 919 showNoneHandler); |
898 } | 920 } |
899 | 921 |
900 /** | 922 /** |
901 * Renders a row that describes all the aggregate values for |columns|. | 923 * Renders a row that describes all the aggregate values for |columns|. |
902 */ | 924 */ |
903 function drawAggregateRow(tbody, aggregates, columns) { | 925 function drawAggregateRow(tbody, aggregates, columns) { |
904 var tr = addNode(tbody, 'tr'); | 926 var tr = addNode(tbody, 'tr'); |
905 tr.className = 'aggregator-row'; | 927 tr.className = 'aggregator-row'; |
906 | 928 |
907 for (var i = 0; i < columns.length; ++i) { | 929 for (var i = 0; i < columns.length; ++i) { |
(...skipping 11 matching lines...) Expand all Loading... |
919 var aggregator = aggregates[key]; | 941 var aggregator = aggregates[key]; |
920 if (aggregator) | 942 if (aggregator) |
921 td.innerText = aggregator.getValueAsText(); | 943 td.innerText = aggregator.getValueAsText(); |
922 } | 944 } |
923 } | 945 } |
924 | 946 |
925 /** | 947 /** |
926 * Renders a table which summarizes all |column| fields for |data|. | 948 * Renders a table which summarizes all |column| fields for |data|. |
927 */ | 949 */ |
928 function drawDataTable(table, data, columns, columnOnClickHandler, | 950 function drawDataTable(table, data, columns, columnOnClickHandler, |
929 currentSortKeys) { | 951 currentSortKeys, limit, expandHandler, shrinkHandler, |
| 952 showAllHandler, showNoneHandler) { |
930 table.className = 'results-table'; | 953 table.className = 'results-table'; |
931 var thead = addNode(table, 'thead'); | 954 var thead = addNode(table, 'thead'); |
932 var tbody = addNode(table, 'tbody'); | 955 var tbody = addNode(table, 'tbody'); |
933 | 956 |
934 drawAggregateRow(thead, data.aggregates, columns); | 957 drawAggregateRow(thead, data.aggregates, columns); |
935 drawTableHeader(thead, columns, columnOnClickHandler, currentSortKeys); | 958 drawTableHeader(thead, columns, columnOnClickHandler, currentSortKeys); |
936 drawTableBody(tbody, data.rows, columns); | 959 drawTableBody(tbody, data.rows, columns, limit); |
| 960 drawTruncationRow(tbody, data.rows.length, limit, columns.length, |
| 961 expandHandler, shrinkHandler, showAllHandler, |
| 962 showNoneHandler); |
| 963 } |
| 964 |
| 965 /** |
| 966 * Renders a row which describes how many rows the table has, how many are |
| 967 * currently hidden, and a set of buttons to show more. |
| 968 */ |
| 969 function drawTruncationRow(tbody, numRows, limit, numColumns, |
| 970 expandHandler, shrinkHandler, showAllHandler, |
| 971 showNoneHandler) { |
| 972 var numHiddenRows = Math.max(numRows - limit, 0); |
| 973 var numVisibleRows = numRows - numHiddenRows; |
| 974 |
| 975 var tr = addNode(tbody, 'tr'); |
| 976 tr.className = 'truncation-row'; |
| 977 var td = addNode(tr, 'td'); |
| 978 td.colSpan = numColumns; |
| 979 |
| 980 addText(td, numRows + ' rows'); |
| 981 if (numHiddenRows > 0) { |
| 982 var s = addNode(td, 'span', ' (' + numHiddenRows + ' hidden) '); |
| 983 s.style.color = 'red'; |
| 984 } |
| 985 |
| 986 if (numVisibleRows > LIMIT_INCREMENT) |
| 987 addNode(td, 'button', 'Show less').onclick = shrinkHandler; |
| 988 if (numVisibleRows > 0) |
| 989 addNode(td, 'button', 'Show none').onclick = showNoneHandler; |
| 990 |
| 991 if (numHiddenRows > 0) { |
| 992 addNode(td, 'button', 'Show more').onclick = expandHandler; |
| 993 addNode(td, 'button', 'Show all').onclick = showAllHandler; |
| 994 } |
937 } | 995 } |
938 | 996 |
939 function drawTableHeader(thead, columns, columnOnClickHandler, | 997 function drawTableHeader(thead, columns, columnOnClickHandler, |
940 currentSortKeys) { | 998 currentSortKeys) { |
941 var tr = addNode(thead, 'tr'); | 999 var tr = addNode(thead, 'tr'); |
942 for (var i = 0; i < columns.length; ++i) { | 1000 for (var i = 0; i < columns.length; ++i) { |
943 var key = columns[i]; | 1001 var key = columns[i]; |
944 var th = addNode(tr, 'th', getNameForKey(key)); | 1002 var th = addNode(tr, 'th', getNameForKey(key)); |
945 th.onclick = columnOnClickHandler.bind(this, key); | 1003 th.onclick = columnOnClickHandler.bind(this, key); |
946 | 1004 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 // value, and hence avoid it overflowing! | 1074 // value, and hence avoid it overflowing! |
1017 var kMinLengthBeforeWrap = 20; | 1075 var kMinLengthBeforeWrap = 20; |
1018 | 1076 |
1019 addText(td, text.substr(0, kMinLengthBeforeWrap)); | 1077 addText(td, text.substr(0, kMinLengthBeforeWrap)); |
1020 for (var i = kMinLengthBeforeWrap; i < text.length; ++i) { | 1078 for (var i = kMinLengthBeforeWrap; i < text.length; ++i) { |
1021 addNode(td, 'wbr'); | 1079 addNode(td, 'wbr'); |
1022 addText(td, text.substr(i, 1)); | 1080 addText(td, text.substr(i, 1)); |
1023 } | 1081 } |
1024 } | 1082 } |
1025 | 1083 |
1026 function drawTableBody(tbody, rows, columns) { | 1084 function drawTableBody(tbody, rows, columns, limit) { |
1027 for (var i = 0; i < rows.length; ++i) { | 1085 for (var i = 0; i < rows.length && i < limit; ++i) { |
1028 var e = rows[i]; | 1086 var e = rows[i]; |
1029 | 1087 |
1030 var tr = addNode(tbody, 'tr'); | 1088 var tr = addNode(tbody, 'tr'); |
1031 | 1089 |
1032 for (var c = 0; c < columns.length; ++c) { | 1090 for (var c = 0; c < columns.length; ++c) { |
1033 var key = columns[c]; | 1091 var key = columns[c]; |
1034 var value = e[key]; | 1092 var value = e[key]; |
1035 | 1093 |
1036 var td = addNode(tr, 'td'); | 1094 var td = addNode(tr, 'td'); |
1037 drawValueToCell(td, key, value); | 1095 drawValueToCell(td, key, value); |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1319 // Clear the results div, sine we may be overwriting older data. | 1377 // Clear the results div, sine we may be overwriting older data. |
1320 var parent = $(RESULTS_DIV_ID); | 1378 var parent = $(RESULTS_DIV_ID); |
1321 parent.innerHTML = ''; | 1379 parent.innerHTML = ''; |
1322 | 1380 |
1323 var columns = this.getVisibleColumnKeys_(); | 1381 var columns = this.getVisibleColumnKeys_(); |
1324 | 1382 |
1325 var columnOnClickHandler = this.onClickColumn_.bind(this); | 1383 var columnOnClickHandler = this.onClickColumn_.bind(this); |
1326 | 1384 |
1327 // Draw each group. | 1385 // Draw each group. |
1328 for (var i = 0; i < this.sortedGroupKeys_.length; ++i) { | 1386 for (var i = 0; i < this.sortedGroupKeys_.length; ++i) { |
1329 var groupData = this.groupedData_[this.sortedGroupKeys_[i]]; | 1387 var k = this.sortedGroupKeys_[i]; |
1330 drawGroup(parent, groupData, columns, | 1388 drawGroup(parent, |
1331 columnOnClickHandler, this.currentSortKeys_); | 1389 this.groupedData_[k], |
| 1390 columns, |
| 1391 columnOnClickHandler, |
| 1392 this.currentSortKeys_, |
| 1393 this.getGroupDisplaySettings_(k), |
| 1394 this.changeGroupDisplayLimit_.bind(this, k, LIMIT_INCREMENT), |
| 1395 this.changeGroupDisplayLimit_.bind(this, k, -LIMIT_INCREMENT), |
| 1396 this.changeGroupDisplayLimit_.bind(this, k, Infinity), |
| 1397 this.changeGroupDisplayLimit_.bind(this, k, -Infinity)); |
1332 } | 1398 } |
1333 }, | 1399 }, |
1334 | 1400 |
| 1401 /** |
| 1402 * Adjusts the row limit for group |groupKey| by |delta|. |
| 1403 */ |
| 1404 changeGroupDisplayLimit_: function(groupKey, delta) { |
| 1405 // Get the current settings for this group. |
| 1406 var settings = this.getGroupDisplaySettings_(groupKey, true); |
| 1407 |
| 1408 // Compute the adjusted limit. |
| 1409 var newLimit = settings.limit; |
| 1410 var totalNumRows = this.groupedData_[groupKey].rows.length; |
| 1411 newLimit = Math.min(totalNumRows, newLimit); |
| 1412 newLimit += delta; |
| 1413 newLimit = Math.max(0, newLimit); |
| 1414 |
| 1415 // Update the settings with the new limit. |
| 1416 settings.limit = newLimit; |
| 1417 |
| 1418 // TODO(eroman): It isn't necessary to redraw *all* the data. Really we |
| 1419 // just need to insert the missing rows (everything else stays the same)! |
| 1420 this.redrawData_(); |
| 1421 }, |
| 1422 |
| 1423 /** |
| 1424 * Returns the rendering settings for group |groupKey|. This includes things |
| 1425 * like how many rows to display in the table. |
| 1426 */ |
| 1427 getGroupDisplaySettings_: function(groupKey, opt_create) { |
| 1428 var settings = this.groupDisplaySettings_[groupKey]; |
| 1429 if (!settings) { |
| 1430 // If we don't have any settings for this group yet, create some |
| 1431 // default ones. |
| 1432 if (groupKey == '[]') { |
| 1433 // (groupKey of '[]' is what we use for ungrouped data). |
| 1434 settings = {limit: INITIAL_UNGROUPED_ROW_LIMIT}; |
| 1435 } else { |
| 1436 settings = {limit: INITIAL_GROUP_ROW_LIMIT}; |
| 1437 } |
| 1438 if (opt_create) |
| 1439 this.groupDisplaySettings_[groupKey] = settings; |
| 1440 } |
| 1441 return settings; |
| 1442 }, |
| 1443 |
1335 init_: function() { | 1444 init_: function() { |
1336 // Data goes through the following pipeline: | 1445 // Data goes through the following pipeline: |
1337 // (1) Raw data received from browser, and transformed into our own | 1446 // (1) Raw data received from browser, and transformed into our own |
1338 // internal row format (where properties are indexed by KEY_* | 1447 // internal row format (where properties are indexed by KEY_* |
1339 // constants.) | 1448 // constants.) |
1340 // (2) We "augment" each row by adding some extra computed columns | 1449 // (2) We "augment" each row by adding some extra computed columns |
1341 // (like averages). | 1450 // (like averages). |
1342 // (3) The rows are merged using current merge settings. | 1451 // (3) The rows are merged using current merge settings. |
1343 // (4) The rows that don't match current search expression are | 1452 // (4) The rows that don't match current search expression are |
1344 // tossed out. | 1453 // tossed out. |
1345 // (5) The rows are organized into "groups" based on current settings, | 1454 // (5) The rows are organized into "groups" based on current settings, |
1346 // and aggregate values are computed for each resulting group. | 1455 // and aggregate values are computed for each resulting group. |
1347 // (6) The rows within each group are sorted using current settings. | 1456 // (6) The rows within each group are sorted using current settings. |
1348 // (7) The grouped rows are drawn to the screen. | 1457 // (7) The grouped rows are drawn to the screen. |
1349 this.flatData_ = []; | 1458 this.flatData_ = []; |
1350 this.mergedData_ = []; | 1459 this.mergedData_ = []; |
1351 this.filteredData_ = []; | 1460 this.filteredData_ = []; |
1352 this.groupedData_ = {}; | 1461 this.groupedData_ = {}; |
1353 this.sortedGroupKeys_ = []; | 1462 this.sortedGroupKeys_ = []; |
1354 | 1463 |
| 1464 this.groupDisplaySettings_ = {}; |
| 1465 |
1355 this.fillSelectionCheckboxes_($(COLUMN_TOGGLES_CONTAINER_ID)); | 1466 this.fillSelectionCheckboxes_($(COLUMN_TOGGLES_CONTAINER_ID)); |
1356 this.fillMergeCheckboxes_($(COLUMN_MERGE_TOGGLES_CONTAINER_ID)); | 1467 this.fillMergeCheckboxes_($(COLUMN_MERGE_TOGGLES_CONTAINER_ID)); |
1357 | 1468 |
1358 $(FILTER_SEARCH_ID).onsearch = this.onChangedFilter_.bind(this); | 1469 $(FILTER_SEARCH_ID).onsearch = this.onChangedFilter_.bind(this); |
1359 | 1470 |
1360 this.currentSortKeys_ = INITIAL_SORT_KEYS.slice(0); | 1471 this.currentSortKeys_ = INITIAL_SORT_KEYS.slice(0); |
1361 this.currentGroupingKeys_ = INITIAL_GROUP_KEYS.slice(0); | 1472 this.currentGroupingKeys_ = INITIAL_GROUP_KEYS.slice(0); |
1362 | 1473 |
1363 this.fillGroupingDropdowns_(); | 1474 this.fillGroupingDropdowns_(); |
1364 this.fillSortingDropdowns_(); | 1475 this.fillSortingDropdowns_(); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1635 groupKey.push(entry); | 1746 groupKey.push(entry); |
1636 } | 1747 } |
1637 | 1748 |
1638 return JSON.stringify(groupKey); | 1749 return JSON.stringify(groupKey); |
1639 }; | 1750 }; |
1640 }, | 1751 }, |
1641 }; | 1752 }; |
1642 | 1753 |
1643 return MainView; | 1754 return MainView; |
1644 })(); | 1755 })(); |
OLD | NEW |