Index: devtools-panel.js |
=================================================================== |
--- a/devtools-panel.js |
+++ b/devtools-panel.js |
@@ -23,17 +23,12 @@ |
(filterTypes) => |
{ |
let filterTypesElem = document.getElementById("filter-type"); |
- let filterStyleElem = document.createElement("style"); |
for (let type of filterTypes) |
{ |
- filterStyleElem.innerHTML += |
- `#items[data-filter-type=${type}] tr:not([data-type=${type}])` + |
- "{display: none;}"; |
let optionNode = document.createElement("option"); |
optionNode.appendChild(document.createTextNode(type)); |
filterTypesElem.appendChild(optionNode); |
} |
- document.body.appendChild(filterStyleElem); |
}); |
function generateFilter(request, domainSpecific) |
@@ -190,10 +185,79 @@ |
row.classList.remove("filtered-by-search"); |
} |
+/** |
+ * Return a generic <tr> placeholder |
+ * double linked with the <tr> itself to simplify |
+ * tbody swaps / filtering of undesired rows. |
+ * @param {HTMLTableRowElement} tr |
+ * @returns {Comment} |
+ */ |
+function getPlaceholder(tr) |
+{ |
+ let placeholder = tr.placeholder; |
+ if (!placeholder) |
+ { |
+ placeholder = document.createComment("placeholder"); |
+ tr.placeholder = placeholder; |
+ placeholder.placeholder = tr; |
+ } |
+ return placeholder; |
+} |
+ |
+/** |
+ * Put back all hidden table rows and eventually |
+ * filters those that do not match the state or type. |
+ * @param {HTMLTableSectionElement} tbody |
+ * @param {DOMStringMap} dataset |
+ */ |
+function updateRows(tbody, dataset) |
+{ |
+ const {filterState, filterType} = dataset; |
+ |
+ // create a list of possible CSS filter |
+ // excluding #background-items from the list of rows to consider |
+ const query = []; |
+ if (filterState) |
+ { |
+ query.push(`tr:not(#background-items):not([data-state="${filterState}"])`); |
+ } |
+ if (filterType) |
+ { |
+ query.push(`tr:not(#background-items):not([data-type="${filterType}"])`); |
+ } |
+ |
+ // use filters to match nodes or retrieve them later on |
+ const selector = query.join(","); |
+ for (const node of tbody.childNodes) |
+ { |
+ // comments linked to table rows |
+ // that won't match selector will be used |
+ // to place their linked row back in the tbody |
+ if ( |
+ node.nodeType === Node.COMMENT_NODE && |
+ (!selector || !node.placeholder.matches(selector)) |
+ ) |
+ { |
+ tbody.replaceChild(node.placeholder, node); |
+ } |
+ } |
+ |
+ // if there is a list of nodes to filter |
+ if (selector) |
+ { |
+ // per each of them put a placeholder inside the tbody |
+ for (const tr of tbody.querySelectorAll(selector)) |
+ { |
+ tbody.replaceChild(getPlaceholder(tr), tr); |
+ } |
+ } |
+} |
+ |
document.addEventListener("DOMContentLoaded", () => |
{ |
let container = document.getElementById("items"); |
let table = container.querySelector("tbody"); |
+ let bgItems = container.querySelector("#background-items"); |
let template = document.querySelector("template").content.firstElementChild; |
document.getElementById("reload").addEventListener("click", () => |
@@ -204,11 +268,13 @@ |
document.getElementById("filter-state").addEventListener("change", (event) => |
{ |
container.dataset.filterState = event.target.value; |
+ updateRows(table, container.dataset); |
}, false); |
document.getElementById("filter-type").addEventListener("change", (event) => |
{ |
container.dataset.filterType = event.target.value; |
+ updateRows(table, container.dataset); |
}, false); |
ext.onMessage.addListener((message) => |
@@ -216,8 +282,16 @@ |
switch (message.type) |
{ |
case "add-record": |
- table.appendChild(createRecord(message.request, message.filter, |
- template)); |
+ let record = createRecord(message.request, message.filter, template); |
+ // what is the official way to know if a request is from background tab? |
+ if (/^SCRIPT|BACKGROUND$/.test(message.request.type)) |
+ { |
+ table.appendChild(record.cloneNode(true)); |
+ } |
+ else |
+ { |
+ table.insertBefore(record, bgItems); |
+ } |
break; |
case "update-record": |