| Index: devtools-panel.js |
| =================================================================== |
| --- a/devtools-panel.js |
| +++ b/devtools-panel.js |
| @@ -18,27 +18,22 @@ |
| "use strict"; |
| let lastFilterQuery = null; |
| browser.runtime.sendMessage({type: "types.get"}, |
| (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) |
| { |
| let filter = request.url.replace(/^[\w-]+:\/+(?:www\.)?/, "||"); |
| let options = []; |
| if (request.type == "POPUP") |
| @@ -168,94 +163,131 @@ |
| { |
| if (element.innerText.search(query) != -1) |
| return false; |
| } |
| } |
| return true; |
| } |
| -function performSearch(table, query) |
| +function performSearch(rows, query) |
| { |
| - for (let row of table.rows) |
| + for (let row of rows) |
| { |
| if (shouldFilterRow(row, query)) |
| row.classList.add("filtered-by-search"); |
| else |
| row.classList.remove("filtered-by-search"); |
| } |
| } |
| function cancelSearch(table) |
| { |
| for (let row of table.rows) |
| row.classList.remove("filtered-by-search"); |
| } |
| +function createZebra(rows, state, type) |
| +{ |
| + let i = 0; |
| + for (const tr of rows) |
| + { |
| + tr.hidden = (state ? tr.dataset.state !== state : false) || |
| + (type ? tr.dataset.type !== type : false); |
| + |
| + if (!tr.hidden) |
| + tr.classList.toggle("odd", !!(i++ % 2)); |
| + } |
| +} |
| + |
| document.addEventListener("DOMContentLoaded", () => |
| { |
| - let container = document.getElementById("items"); |
| - let table = container.querySelector("tbody"); |
| - let template = document.querySelector("template").content.firstElementChild; |
| + const container = document.getElementById("items"); |
| + const foregroundTable = container.querySelector("table.foreground tbody"); |
| + const backgroundTable = container.querySelector("table.background tbody"); |
| + const template = document.querySelector("template") |
| + .content.firstElementChild; |
| + |
| + // We update rows by message index. |
| + // Since we don't have a linear collection of rows anymore, |
| + // all records, as row, will be indexed in here. |
| + // Memory wise, this is just a collection that points |
| + // at live DOM nodes (rows), so this does not imply |
| + // higher memory consumption, leaks, or any other concern. |
| + const records = []; |
| + |
| + const filterState = document.getElementById("filter-state"); |
| + const filterType = document.getElementById("filter-type"); |
| + |
| + const updateRowsState = () => |
| + { |
| + const state = filterState.value; |
| + const type = filterType.value; |
| + createZebra(foregroundTable.querySelectorAll("tr"), state, type); |
| + const notFirstTR = "tr:not(:first-child)"; |
| + createZebra(backgroundTable.querySelectorAll(notFirstTR), state, type); |
| + }; |
| document.getElementById("reload").addEventListener("click", () => |
| { |
| ext.devtools.inspectedWindow.reload(); |
| }, false); |
| - document.getElementById("filter-state").addEventListener("change", (event) => |
| - { |
| - container.dataset.filterState = event.target.value; |
| - }, false); |
| - |
| - document.getElementById("filter-type").addEventListener("change", (event) => |
| - { |
| - container.dataset.filterType = event.target.value; |
| - }, false); |
| + // update rows visibility state per each change |
| + filterState.addEventListener("change", updateRowsState, false); |
| + filterType.addEventListener("change", updateRowsState, false); |
| ext.onMessage.addListener((message) => |
| { |
| switch (message.type) |
| { |
| case "add-record": |
| - table.appendChild(createRecord(message.request, message.filter, |
| - template)); |
| + const record = createRecord(message.request, message.filter, template); |
| + records.push(record); |
| + // waiting for 6402 to ship |
| + if (message.request.docDomain == null) |
| + backgroundTable.appendChild(record); |
| + else |
| + foregroundTable.appendChild(record); |
| break; |
| case "update-record": |
| - let oldRow = table.getElementsByTagName("tr")[message.index]; |
| + let oldRow = records[message.index]; |
| let newRow = createRecord(message.request, message.filter, template); |
| + records[message.index] = newRow; |
| oldRow.parentNode.replaceChild(newRow, oldRow); |
| newRow.classList.add("changed"); |
| container.classList.add("has-changes"); |
| break; |
| case "remove-record": |
| - let row = table.getElementsByTagName("tr")[message.index]; |
| + let row = records.splice(message.index, 1)[0]; |
| row.parentNode.removeChild(row); |
| container.classList.add("has-changes"); |
| break; |
| case "reset": |
| - table.innerHTML = ""; |
| + records.splice(0); |
| + foregroundTable.innerHTML = ""; |
| container.classList.remove("has-changes"); |
| break; |
| } |
| + updateRowsState(); |
| }); |
| window.addEventListener("message", (event) => |
| { |
| switch (event.data.type) |
| { |
| case "performSearch": |
| - performSearch(table, event.data.queryString); |
| + performSearch(records, event.data.queryString); |
| lastFilterQuery = event.data.queryString; |
| break; |
| case "cancelSearch": |
| - cancelSearch(table); |
| + cancelSearch(records); |
| lastFilterQuery = null; |
| break; |
| } |
| }); |
| // Since Chrome 54 the themeName is accessible, for earlier versions we must |
| // assume the default theme is being used. |
| // https://bugs.chromium.org/p/chromium/issues/detail?id=608869 |