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

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: Fix js styles for presubmit 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
« no previous file with comments | « chrome/browser/resources/feedback/js/feedback.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 {HTMLElement} button The expand button.
34 * @param {HTMLElement} valueDiv The div that contains the multiline logs.
35 * @param {number} delayFactor A value used for increasing the delay after which
36 * the 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 {HTMLElement} button The expand button.
57 * @param {HTMLElement} 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));
158
115 return row; 159 return row;
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
121 * will be appended.
122 * @param {Object} systemInfo The system information that will be used to fill
123 * the table.
124 */ 164 */
125 function createTable(table, systemInfo) { 165 function finishPageLoading() {
126 for (var key in systemInfo) { 166 $('collapseAllBtn').onclick = collapseAll;
127 var item = systemInfo[key]; 167 $('expandAllBtn').onclick = expandAll;
128 table.appendChild(createTableRow(item['key'], item['value'])); 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 if (tableCreationClosuresQueue.length > 0) {
181 // Post a task to process the next item in the queue.
182 setTimeout(processQueue, STANDARD_DELAY_MS);
129 } 183 }
130 } 184 }
131 185
132 /** 186 /**
133 * The callback which will be invoked by the parent window, when the system 187 * Creates a closure that creates a table row for the given key and value.
134 * information is ready. 188 * @param {string} key The name of the log.
189 * @param {string} value The contents of the log.
190 * @return {function():void} A closure that creates a row for the given log.
191 */
192 function createTableRowWrapper(key, value) {
193 return function() {
194 $('detailsTable').appendChild(createTableRow(key, value));
195 };
196 }
197
198 /**
199 * Creates closures to build the system information table row by row
200 * incrementally.
135 * @param {Object} systemInfo The system information that will be used to fill 201 * @param {Object} systemInfo The system information that will be used to fill
136 * the table. 202 * the table.
137 */ 203 */
138 function onSysInfoReady(systemInfo) { 204 function createTable(systemInfo) {
139 createTable($('detailsTable'), systemInfo); 205 for (var key in systemInfo) {
206 var item = systemInfo[key];
207 tableCreationClosuresQueue.push(
208 createTableRowWrapper(item['key'], item['value']));
209 }
140 210
141 $('collapseAllBtn').onclick = collapseAll; 211 tableCreationClosuresQueue.push(finishPageLoading);
142 $('expandAllBtn').onclick = expandAll;
143 212
144 collapseMultiLineStrings(); 213 processQueue();
145
146 $('status').textContent = '';
147 } 214 }
148 215
149 /** 216 /**
150 * Initializes the page when the window is loaded. 217 * Initializes the page when the window is loaded.
151 */ 218 */
152 window.onload = function() { 219 window.onload = function() {
153 loadTimeData = getLoadTimeData(); 220 loadTimeData = getLoadTimeData();
154 i18nTemplate.process(document, loadTimeData); 221 i18nTemplate.process(document, loadTimeData);
155 getFullSystemInfo(onSysInfoReady); 222 getFullSystemInfo(createTable);
156 }; 223 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/feedback/js/feedback.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698