Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: chrome/browser/resources/feedback/js/sys_info.js

Issue 2403503003: Optimize the table creation in the Sys Info page of the feedback app (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 /** 5 /**
6 * The global load time data that contains the localized strings that we will 6 * The global load time data that contains the localized strings that we will
7 * get from the main page when this page first loads. 7 * get from the main page when this page first loads.
8 */ 8 */
9 var loadTimeData = null; 9 var loadTimeData = null;
10 10
11 /**
12 * A queue of a sequence of closures that will incrementally build the sys info
13 * html table.
14 */
15 var tableCreationClosuresQueue = [];
16
17 /**
18 * The time used to post delayed tasks in MS. Currently set to be enough for two
19 * frames.
20 */
21 var STANDARD_DELAY_MS = 32;
22
11 function getValueDivForButton(button) { 23 function getValueDivForButton(button) {
12 return $(button.id.substr(0, button.id.length - 4)); 24 return $(button.id.substr(0, button.id.length - 4));
13 } 25 }
14 26
15 function getButtonForValueDiv(valueDiv) { 27 function getButtonForValueDiv(valueDiv) {
16 return $(valueDiv.id + '-btn'); 28 return $(valueDiv.id + '-btn');
17 } 29 }
18 30
19 /** 31 /**
32 * Expands the multiline table cell that contains the given valueDiv.
33 * @param button The expand button.
34 * @param valueDiv The div that contains the multiline logs.
35 * @param delayFactor A value used for increasing the delay after which the
36 * cell will be expanded. Useful for expandAll() since it expands the
37 * multiline cells one after another with each expension done slightly after
38 * the previous one.
39 */
40 function expand(button, valueDiv, delayFactor) {
41 button.textContent = loadTimeData.getString('sysinfoPageCollapseBtn');
42 // Show the spinner container.
43 var valueCell = valueDiv.parentNode;
44 valueCell.firstChild.hidden = false;
45 // Expanding huge logs can take a very long time, so we do it after a delay
46 // to have a chance to render the spinner.
47 setTimeout(function() {
48 valueCell.className = 'number-expanded';
49 // Hide the spinner container.
50 valueCell.firstChild.hidden = true;
51 }, STANDARD_DELAY_MS * delayFactor);
52 }
53
54 /**
55 * Collapses the multiline table cell that contains the given valueDiv.
56 * @param button The expand button.
57 * @param valueDiv The div that contains the multiline logs.
58 */
59 function collapse(button, valueDiv) {
60 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn');
61 valueDiv.parentNode.className = 'number-collapsed';
62 }
63
64 /**
20 * Toggles whether an item is collapsed or expanded. 65 * Toggles whether an item is collapsed or expanded.
21 */ 66 */
22 function changeCollapsedStatus() { 67 function changeCollapsedStatus() {
23 var valueDiv = getValueDivForButton(this); 68 var valueDiv = getValueDivForButton(this);
24 if (valueDiv.parentNode.className == 'number-collapsed') { 69 if (valueDiv.parentNode.className == 'number-collapsed')
25 valueDiv.parentNode.className = 'number-expanded'; 70 expand(this, valueDiv, 1);
26 this.textContent = loadTimeData.getString('sysinfoPageCollapseBtn'); 71 else
27 } else { 72 collapse(this, valueDiv);
28 valueDiv.parentNode.className = 'number-collapsed';
29 this.textContent = loadTimeData.getString('sysinfoPageExpandBtn');
30 }
31 } 73 }
32 74
33 /** 75 /**
34 * Collapses all log items. 76 * Collapses all log items.
35 */ 77 */
36 function collapseAll() { 78 function collapseAll() {
37 var valueDivs = document.getElementsByClassName('stat-value'); 79 var valueDivs = document.getElementsByClassName('stat-value');
38 for (var i = 0; i < valueDivs.length; i++) { 80 for (var i = 0; i < valueDivs.length; ++i) {
81 if (valueDivs[i].parentNode.className != 'number-expanded')
82 continue;
39 var button = getButtonForValueDiv(valueDivs[i]); 83 var button = getButtonForValueDiv(valueDivs[i]);
40 if (button && button.className != 'button-hidden') { 84 if (button)
41 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn'); 85 collapse(button, valueDivs[i]);
42 valueDivs[i].parentNode.className = 'number-collapsed';
43 }
44 } 86 }
45 } 87 }
46 88
47 /** 89 /**
48 * Expands all log items. 90 * Expands all log items.
49 */ 91 */
50 function expandAll() { 92 function expandAll() {
51 var valueDivs = document.getElementsByClassName('stat-value'); 93 var valueDivs = document.getElementsByClassName('stat-value');
52 for (var i = 0; i < valueDivs.length; i++) { 94 for (var i = 0; i < valueDivs.length; ++i) {
95 if (valueDivs[i].parentNode.className != 'number-collapsed')
96 continue;
53 var button = getButtonForValueDiv(valueDivs[i]); 97 var button = getButtonForValueDiv(valueDivs[i]);
54 if (button && button.className != 'button-hidden') { 98 if (button)
55 button.textContent = loadTimeData.getString('sysinfoPageCollapseBtn'); 99 expand(button, valueDivs[i], i + 1);
56 valueDivs[i].parentNode.className = 'number-expanded';
57 }
58 } 100 }
59 } 101 }
60 102
61 /**
62 * Collapse only those log items with multi-line values.
63 */
64 function collapseMultiLineStrings() {
65 var valueDivs = document.getElementsByClassName('stat-value');
66 var nameDivs = document.getElementsByClassName('stat-name');
67 for (var i = 0; i < valueDivs.length; i++) {
68 var button = getButtonForValueDiv(valueDivs[i]);
69 button.onclick = changeCollapsedStatus;
70 if (valueDivs[i].scrollHeight > (nameDivs[i].scrollHeight * 2)) {
71 button.className = '';
72 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn');
73 valueDivs[i].parentNode.className = 'number-collapsed';
74 } else {
75 button.className = 'button-hidden';
76 valueDivs[i].parentNode.className = 'number';
77 }
78 }
79 }
80
81 function createNameCell(key) { 103 function createNameCell(key) {
82 var nameCell = document.createElement('td'); 104 var nameCell = document.createElement('td');
83 nameCell.setAttribute('class', 'name'); 105 nameCell.setAttribute('class', 'name');
84 var nameDiv = document.createElement('div'); 106 var nameDiv = document.createElement('div');
85 nameDiv.setAttribute('class', 'stat-name'); 107 nameDiv.setAttribute('class', 'stat-name');
86 nameDiv.appendChild(document.createTextNode(key)); 108 nameDiv.appendChild(document.createTextNode(key));
87 nameCell.appendChild(nameDiv); 109 nameCell.appendChild(nameDiv);
88 return nameCell; 110 return nameCell;
89 } 111 }
90 112
91 function createButtonCell(key) { 113 function createButtonCell(key, isMultiLine) {
92 var buttonCell = document.createElement('td'); 114 var buttonCell = document.createElement('td');
93 buttonCell.setAttribute('class', 'button-cell'); 115 buttonCell.setAttribute('class', 'button-cell');
94 var button = document.createElement('button'); 116
95 button.setAttribute('id', '' + key + '-value-btn'); 117 if (isMultiLine) {
96 buttonCell.appendChild(button); 118 var button = document.createElement('button');
119 button.setAttribute('id', '' + key + '-value-btn');
120 button.onclick = changeCollapsedStatus;
121 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn');
122 buttonCell.appendChild(button);
123 }
124
97 return buttonCell; 125 return buttonCell;
98 } 126 }
99 127
100 function createValueCell(key, value) { 128 function createValueCell(key, value, isMultiLine) {
101 var valueCell = document.createElement('td'); 129 var valueCell = document.createElement('td');
102 var valueDiv = document.createElement('div'); 130 var valueDiv = document.createElement('div');
103 valueDiv.setAttribute('class', 'stat-value'); 131 valueDiv.setAttribute('class', 'stat-value');
104 valueDiv.setAttribute('id', '' + key + '-value'); 132 valueDiv.setAttribute('id', '' + key + '-value');
105 valueDiv.appendChild(document.createTextNode(value)); 133 valueDiv.appendChild(document.createTextNode(value));
134
135 if (isMultiLine) {
136 valueCell.className = 'number-collapsed';
137 var loadingContainer = $('spinner-container').cloneNode(true);
138 loadingContainer.setAttribute('id', '' + key + '-value-loading');
139 loadingContainer.hidden = true;
140 valueCell.appendChild(loadingContainer);
141 } else {
142 valueCell.className = 'number';
143 }
144
106 valueCell.appendChild(valueDiv); 145 valueCell.appendChild(valueDiv);
107 return valueCell; 146 return valueCell;
108 } 147 }
109 148
110 function createTableRow(key, value) { 149 function createTableRow(key, value) {
111 var row = document.createElement('tr'); 150 var row = document.createElement('tr');
151
152 // Avoid using element.scrollHeight as it's very slow. crbug.com/653968.
153 var isMultiLine = value.split('\n').length > 2 || value.length > 1000;
154
112 row.appendChild(createNameCell(key)); 155 row.appendChild(createNameCell(key));
113 row.appendChild(createButtonCell(key)); 156 row.appendChild(createButtonCell(key, isMultiLine));
114 row.appendChild(createValueCell(key, value)); 157 row.appendChild(createValueCell(key, value, isMultiLine));
115 return row; 158
159 $('detailsTable').appendChild(row);
xiyuan 2016/10/10 16:57:35 nit: move appendChild into the wrapper function wh
afakhry 2016/10/12 16:12:07 Done.
116 } 160 }
117 161
118 /** 162 /**
119 * Builds the system information table row by row. 163 * Finalize the page after the content has been loaded.
120 * @param {Element} table The DOM table element to which the newly created rows 164 */
121 * will be appended. 165 function finishPageLoading() {
166 $('collapseAllBtn').onclick = collapseAll;
167 $('expandAllBtn').onclick = expandAll;
168
169 $('spinner-container').hidden = true;
170 }
171
172 /**
173 * Pops a closure from the front of the queue and executes it.
174 */
175 function processQueue() {
176 var closure = tableCreationClosuresQueue.shift();
177 if (closure)
178 closure();
179 }
180
181 /**
182 * Creates a closure that creates a table row for the given key and value.
183 */
184 function createTableRowWrapper(key, value) {
185 return function() {
186 createTableRow(key, value);
187
188 // Post a task to process the next item in the queue.
189 setTimeout(processQueue, STANDARD_DELAY_MS);
xiyuan 2016/10/10 16:57:35 nit: move this into processQueue to keep schedulin
afakhry 2016/10/12 16:12:07 Done.
190 };
191 }
192
193 /**
194 * Creates closures to build the system information table row by row
195 * incrementally.
122 * @param {Object} systemInfo The system information that will be used to fill 196 * @param {Object} systemInfo The system information that will be used to fill
123 * the table. 197 * the table.
124 */ 198 */
125 function createTable(table, systemInfo) { 199 function createTable(systemInfo) {
126 for (var key in systemInfo) { 200 for (var key in systemInfo) {
127 var item = systemInfo[key]; 201 var item = systemInfo[key];
128 table.appendChild(createTableRow(item['key'], item['value'])); 202 tableCreationClosuresQueue.push(
203 createTableRowWrapper(item['key'], item['value']));
129 } 204 }
205
206 tableCreationClosuresQueue.push(finishPageLoading);
207
208 processQueue();
130 } 209 }
131 210
132 /** 211 /**
133 * The callback which will be invoked by the parent window, when the system
134 * information is ready.
135 * @param {Object} systemInfo The system information that will be used to fill
136 * the table.
137 */
138 function onSysInfoReady(systemInfo) {
139 createTable($('detailsTable'), systemInfo);
140
141 $('collapseAllBtn').onclick = collapseAll;
142 $('expandAllBtn').onclick = expandAll;
143
144 collapseMultiLineStrings();
145
146 $('status').textContent = '';
147 }
148
149 /**
150 * Initializes the page when the window is loaded. 212 * Initializes the page when the window is loaded.
151 */ 213 */
152 window.onload = function() { 214 window.onload = function() {
153 loadTimeData = getLoadTimeData(); 215 loadTimeData = getLoadTimeData();
154 i18nTemplate.process(document, loadTimeData); 216 i18nTemplate.process(document, loadTimeData);
155 getFullSystemInfo(onSysInfoReady); 217 getFullSystemInfo(createTable);
156 }; 218 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698