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,11 +185,81 @@ |
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; |
+ const records = []; |
document.getElementById("reload").addEventListener("click", () => |
{ |
@@ -204,11 +269,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,25 +283,38 @@ |
switch (message.type) |
{ |
case "add-record": |
- table.appendChild(createRecord(message.request, message.filter, |
- template)); |
+ let record = createRecord(message.request, message.filter, template); |
+ records.push(record); |
+ // what is the official way to know if a request is from background tab? |
+ if (/^SCRIPT|BACKGROUND$/.test(message.request.type)) |
+ { |
+ table.appendChild(record); |
+ } |
+ else |
+ { |
+ table.insertBefore(record, bgItems); |
+ } |
break; |
case "update-record": |
- let oldRow = table.getElementsByTagName("tr")[message.index]; |
+ let oldRow = records[message.index]; |
let newRow = createRecord(message.request, message.filter, template); |
- oldRow.parentNode.replaceChild(newRow, oldRow); |
+ records[message.index] = newRow; |
+ let liveRow = oldRow.parentNode ? oldRow : oldRow.placeholder; |
+ liveRow.parentNode.replaceChild(newRow, liveRow); |
newRow.classList.add("changed"); |
container.classList.add("has-changes"); |
break; |
case "remove-record": |
- let row = table.getElementsByTagName("tr")[message.index]; |
- row.parentNode.removeChild(row); |
+ let row = records.splice(message.index, 1)[0]; |
+ let live = row.parentNode ? row : row.placeholder; |
+ live.parentNode.removeChild(live); |
container.classList.add("has-changes"); |
break; |
case "reset": |
+ records.splice(0); |
table.innerHTML = ""; |
container.classList.remove("has-changes"); |
break; |