Skip to content
This repository was archived by the owner on Jul 23, 2024. It is now read-only.

Commit dafbdeb

Browse files
committed
Implement async rendering in order to begin to show asap
1 parent 831fd0a commit dafbdeb

2 files changed

Lines changed: 73 additions & 118 deletions

File tree

extension/sidebar-pane.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,6 @@
165165
display: block;
166166
}
167167

168-
#subtree.processing ul {
169-
display: none;
170-
}
171-
172168
#subtree aside label {
173169
display: flex;
174170
align-items: center;

extension/sidebar-pane.js

Lines changed: 73 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -16,148 +16,112 @@ async function _update() {
1616

1717
async function _updateSelectedNode(selectedNode) {
1818
const issueListEl = document.querySelector("#selected ul");
19+
issueListEl.innerHTML = "";
1920

20-
if (!_isValidElement(selectedNode)) {
21-
_render([], issueListEl);
22-
return;
23-
}
24-
25-
const issues = [];
26-
27-
const { actorID, attributes, nodeName } = selectedNode;
28-
issues.push(
29-
..._webcompat.getHTMLElementIssues(nodeName, attributes, _targetBrowsers));
30-
31-
const declarationBlocks =
32-
await browser.experiments.inspectedNode.getStyle(actorID, true);
33-
for (const declarations of declarationBlocks) {
34-
issues.push(
35-
..._webcompat.getCSSDeclarationBlockIssues(declarations, _targetBrowsers));
36-
}
37-
38-
_render(issues, issueListEl);
21+
_asyncRenderNodes(0, [selectedNode], true, issueListEl, []).then(() => {
22+
if (!issueListEl.querySelector("li")) {
23+
_renderNoIssue(issueListEl);
24+
}
25+
});
3926
}
4027

4128
async function _updateSubtree(selectedNode) {
4229
const subtreeEl = document.getElementById("subtree");
4330
const issueListEl = subtreeEl.querySelector("ul");
4431

45-
if (!_isValidElement(selectedNode)) {
46-
_render([], issueListEl);
47-
return;
48-
}
49-
50-
const issues = [];
51-
5232
subtreeEl.classList.add("processing");
5333
const progressEl = subtreeEl.querySelector("aside label");
5434

5535
progressEl.textContent = "Getting all descendants of the selected node";
5636
const nodesInSubtree = await browser.experiments.inspectedNode.getNodesInSubtree();
5737

58-
progressEl.textContent = "Getting web compatibility issues for HTML element";
59-
for (const node of nodesInSubtree) {
60-
if (!_isValidElement(node)) {
61-
continue
38+
progressEl.textContent = "Getting web compatibility issues";
39+
issueListEl.innerHTML = "";
40+
_asyncRenderNodes(0, nodesInSubtree, false, issueListEl, []).then(() => {
41+
subtreeEl.classList.remove("processing");
42+
if (!issueListEl.querySelector("li")) {
43+
_renderNoIssue(issueListEl);
6244
}
45+
});
46+
}
6347

64-
const { attributes, nodeName } = node;
65-
issues.push(
66-
...
67-
_webcompat.getHTMLElementIssues(nodeName, attributes, _targetBrowsers)
68-
.map(issue => {
69-
issue.node = node;
70-
return issue;
71-
})
72-
)
48+
async function _asyncRenderNodes(index, nodes, skipPseudo, listEl, groupsCache) {
49+
const node = nodes[index];
50+
if (!node) {
51+
return;
7352
}
7453

75-
progressEl.textContent = "Getting web compatibility issues for CSS styles";
76-
for (const node of nodesInSubtree) {
77-
if (!_isValidElement(node)) {
78-
continue
79-
}
54+
if (_isValidElement(node)) {
55+
const { actorID, attributes, nodeName } = node;
56+
const htmlIssues =
57+
_webcompat.getHTMLElementIssues(nodeName, attributes, _targetBrowsers);
58+
_appendIssues(htmlIssues, node, listEl, groupsCache);
8059

8160
const declarationBlocks =
82-
await browser.experiments.inspectedNode.getStyle(node.actorID, false);
61+
await browser.experiments.inspectedNode.getStyle(actorID, skipPseudo);
8362
for (const declarations of declarationBlocks) {
84-
issues.push(
85-
...
86-
_webcompat.getCSSDeclarationBlockIssues(declarations, _targetBrowsers)
87-
.map(issue => {
88-
issue.node = node;
89-
return issue;
90-
})
91-
);
63+
const cssIssues =
64+
_webcompat.getCSSDeclarationBlockIssues(declarations, _targetBrowsers);
65+
_appendIssues(cssIssues, node, listEl, groupsCache);
9266
}
9367
}
9468

95-
progressEl.textContent = "Grouping all issues";
96-
const issueGroups = _groupIssues(issues);
97-
98-
progressEl.textContent = "Rendering all issues";
99-
_render(issueGroups, issueListEl);
100-
101-
subtreeEl.classList.remove("processing");
69+
await _asyncRenderNodes(index + 1, nodes, skipPseudo, listEl, groupsCache);
10270
}
10371

104-
/**
105-
* Group by the issue cause.
106-
* @param {Array} issues
107-
* The issue list which WebCompat library returns. Also the issue in the list
108-
* assume to contain the node information additionaly.
109-
* @return {Array}
110-
* Array of issues grouped. The issue has `nodes` attribute which contains the
111-
* node informations where caused the issue.
112-
*/
113-
function _groupIssues(issues) {
114-
const issueGroups = [];
72+
function _isValidElement({ nodeType, isCustomElement }) {
73+
return nodeType === Node.ELEMENT_NODE && !isCustomElement;
74+
}
11575

76+
function _appendIssues(issues, node, listEl, issueGroups) {
11677
for (const issue of issues) {
117-
let issueGroup = issueGroups.find(i => {
118-
return i.type === issue.type &&
119-
i.property === issue.property &&
120-
i.element === issue.element &&
121-
i.attribute === issue.attribute &&
122-
i.value === issue.value;
123-
});
124-
125-
if (!issueGroup) {
126-
issueGroup = Object.assign({}, issue, { nodes: [], node: undefined });
127-
issueGroups.push(issueGroup);
128-
}
129-
130-
const isNodeContainedInGroup = issueGroup.nodes.some(n => {
131-
return n.nodeName === issue.node.nodeName &&
132-
n.nodeType === issue.node.nodeType &&
133-
n.id === issue.node.id &&
134-
n.className === issue.node.className;
135-
});
78+
_appendIssue(issue, node, listEl, issueGroups);
79+
}
80+
}
13681

137-
if (!isNodeContainedInGroup) {
138-
issueGroup.nodes.push(issue.node);
139-
}
82+
function _appendIssue(issue, node, listEl, issueGroups) {
83+
let issueGroup = issueGroups.find(i => {
84+
return i.type === issue.type &&
85+
i.property === issue.property &&
86+
i.element === issue.element &&
87+
i.attribute === issue.attribute &&
88+
i.value === issue.value;
89+
});
90+
91+
if (!issueGroup) {
92+
issueGroup = Object.assign({}, issue, { nodes: [] });
93+
issueGroups.push(issueGroup);
14094
}
14195

142-
return issueGroups;
143-
}
96+
const isNodeContainedInGroup = issueGroup.nodes.some(n => {
97+
return n.nodeName === node.nodeName &&
98+
n.nodeType === node.nodeType &&
99+
n.id === node.id &&
100+
n.className === node.className;
101+
});
102+
103+
if (!isNodeContainedInGroup) {
104+
issueGroup.nodes.push(node);
105+
106+
if (issueGroup.view) {
107+
// Remove occurrences element in order to update occurrences only.
108+
issueGroup.view.querySelector(".occurrences").remove();
109+
} else {
110+
// Append new view for this issue.
111+
const view = _renderIssue(issueGroup);
112+
listEl.appendChild(view);
113+
issueGroup.view = view;
114+
}
144115

145-
function _isValidElement({ nodeType, isCustomElement }) {
146-
return nodeType === Node.ELEMENT_NODE && !isCustomElement;
116+
issueGroup.view.append(_renderOccurrences(issueGroup.nodes));
117+
}
147118
}
148119

149-
function _render(issues, issueListEl) {
150-
issueListEl.innerHTML = "";
151120

152-
if (!issues.length) {
153-
const noIssueEl = document.createElement("li");
154-
noIssueEl.textContent = "No issues";
155-
issueListEl.appendChild(noIssueEl);
156-
} else {
157-
for (const issue of issues) {
158-
issueListEl.appendChild(_renderIssue(issue));
159-
}
160-
}
121+
function _renderNoIssue(listEl) {
122+
const noIssueEl = document.createElement("li");
123+
noIssueEl.textContent = "No issues";
124+
listEl.appendChild(noIssueEl);
161125
}
162126

163127
function _renderIssue(issue) {
@@ -168,15 +132,10 @@ function _renderIssue(issue) {
168132
issueEl.appendChild(predicateEl);
169133

170134
issueEl.classList.add((issue.deprecated ? "warning" : "information"));
171-
172-
if (issue.nodes) {
173-
issueEl.append(_renderOccurrences(issue));
174-
}
175-
176135
return issueEl;
177136
}
178137

179-
function _renderOccurrences({ nodes }) {
138+
function _renderOccurrences(nodes) {
180139
const occurrencesEl = document.createElement("section");
181140
occurrencesEl.classList.add("occurrences");
182141

0 commit comments

Comments
 (0)