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; | |
jar (doing other things)
2011/11/17 14:18:40
Excellent! You beat me to the punch! I was going
| |
550 | |
551 /** | |
552 * The initial number of rows to display (rest are hidden) for each group. | |
553 */ | |
554 var INITIAL_GROUP_ROW_LIMIT = 10; | |
jar (doing other things)
2011/11/17 14:18:40
I'm suspicious that this should be lower. IMO, it
eroman
2011/11/17 19:06:51
It should be easy to change these policies as we p
| |
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; | |
jar (doing other things)
2011/11/17 14:18:40
IF you do go for the smaller initial limit... then
| |
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); | |
jar (doing other things)
2011/11/17 14:18:40
nit: Not critical to this CL: Sometimes when I see
eroman
2011/11/17 19:06:51
I fully agree, the arguments here are getting unwi
| |
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)); | |
jar (doing other things)
2011/11/17 14:18:40
As used here... the arguments are real clear... bu
eroman
2011/11/17 19:06:51
I will fix this in a followup.
| |
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 |