| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| 3  * Copyright (C) 2006-present eyeo GmbH | 3  * Copyright (C) 2006-present eyeo GmbH | 
| 4  * | 4  * | 
| 5  * Adblock Plus is free software: you can redistribute it and/or modify | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
| 6  * it under the terms of the GNU General Public License version 3 as | 6  * it under the terms of the GNU General Public License version 3 as | 
| 7  * published by the Free Software Foundation. | 7  * published by the Free Software Foundation. | 
| 8  * | 8  * | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 12  * GNU General Public License for more details. | 12  * GNU General Public License for more details. | 
| 13  * | 13  * | 
| 14  * You should have received a copy of the GNU General Public License | 14  * You should have received a copy of the GNU General Public License | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 16  */ | 16  */ | 
| 17 | 17 | 
| 18 "use strict"; | 18 "use strict"; | 
| 19 | 19 | 
| 20 let lastFilterQuery = null; | 20 let lastFilterQuery = null; | 
| 21 | 21 | 
| 22 browser.runtime.sendMessage({type: "types.get"}, | 22 browser.runtime.sendMessage({type: "types.get"}, | 
| 23   (filterTypes) => | 23   (filterTypes) => | 
| 24   { | 24   { | 
| 25     let filterTypesElem = document.getElementById("filter-type"); | 25     let filterTypesElem = document.getElementById("filter-type"); | 
| 26     let filterStyleElem = document.createElement("style"); |  | 
| 27     for (let type of filterTypes) | 26     for (let type of filterTypes) | 
| 28     { | 27     { | 
| 29       filterStyleElem.innerHTML += |  | 
| 30         `#items[data-filter-type=${type}] tr:not([data-type=${type}])` + |  | 
| 31         "{display: none;}"; |  | 
| 32       let optionNode = document.createElement("option"); | 28       let optionNode = document.createElement("option"); | 
| 33       optionNode.appendChild(document.createTextNode(type)); | 29       optionNode.appendChild(document.createTextNode(type)); | 
| 34       filterTypesElem.appendChild(optionNode); | 30       filterTypesElem.appendChild(optionNode); | 
| 35     } | 31     } | 
| 36     document.body.appendChild(filterStyleElem); |  | 
| 37   }); | 32   }); | 
| 38 | 33 | 
| 39 function generateFilter(request, domainSpecific) | 34 function generateFilter(request, domainSpecific) | 
| 40 { | 35 { | 
| 41   let filter = request.url.replace(/^[\w-]+:\/+(?:www\.)?/, "||"); | 36   let filter = request.url.replace(/^[\w-]+:\/+(?:www\.)?/, "||"); | 
| 42   let options = []; | 37   let options = []; | 
| 43 | 38 | 
| 44   if (request.type == "POPUP") | 39   if (request.type == "POPUP") | 
| 45   { | 40   { | 
| 46     options.push("popup"); | 41     options.push("popup"); | 
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 183       row.classList.remove("filtered-by-search"); | 178       row.classList.remove("filtered-by-search"); | 
| 184   } | 179   } | 
| 185 } | 180 } | 
| 186 | 181 | 
| 187 function cancelSearch(table) | 182 function cancelSearch(table) | 
| 188 { | 183 { | 
| 189   for (let row of table.rows) | 184   for (let row of table.rows) | 
| 190     row.classList.remove("filtered-by-search"); | 185     row.classList.remove("filtered-by-search"); | 
| 191 } | 186 } | 
| 192 | 187 | 
|  | 188 /** | 
|  | 189  * Return a generic <tr> placeholder | 
|  | 190  * double linked with the <tr> itself to simplify | 
|  | 191  * tbody swaps / filtering of undesired rows. | 
|  | 192  * @param {HTMLTableRowElement} tr | 
|  | 193  * @returns {Comment} | 
|  | 194  */ | 
|  | 195 function getPlaceholder(tr) | 
|  | 196 { | 
|  | 197   let placeholder = tr.placeholder; | 
|  | 198   if (!placeholder) | 
|  | 199   { | 
|  | 200     placeholder = document.createComment("placeholder"); | 
|  | 201     tr.placeholder = placeholder; | 
|  | 202     placeholder.placeholder = tr; | 
|  | 203   } | 
|  | 204   return placeholder; | 
|  | 205 } | 
|  | 206 | 
|  | 207 /** | 
|  | 208  * Put back all hidden table rows and eventually | 
|  | 209  * filters those that do not match the state or type. | 
|  | 210  * @param {HTMLTableSectionElement} tbody | 
|  | 211  * @param {DOMStringMap} dataset | 
|  | 212  */ | 
|  | 213 function updateRows(tbody, dataset) | 
|  | 214 { | 
|  | 215   const {filterState, filterType} = dataset; | 
|  | 216 | 
|  | 217   // create a list of possible CSS filter | 
|  | 218   // excluding #background-items from the list of rows to consider | 
|  | 219   const query = []; | 
|  | 220   if (filterState) | 
|  | 221   { | 
|  | 222     query.push(`tr:not(#background-items):not([data-state="${filterState}"])`); | 
|  | 223   } | 
|  | 224   if (filterType) | 
|  | 225   { | 
|  | 226     query.push(`tr:not(#background-items):not([data-type="${filterType}"])`); | 
|  | 227   } | 
|  | 228 | 
|  | 229   // use filters to match nodes or retrieve them later on | 
|  | 230   const selector = query.join(","); | 
|  | 231   for (const node of tbody.childNodes) | 
|  | 232   { | 
|  | 233     // comments linked to table rows | 
|  | 234     // that won't match selector will be used | 
|  | 235     // to place their linked row back in the tbody | 
|  | 236     if ( | 
|  | 237       node.nodeType === Node.COMMENT_NODE && | 
|  | 238       (!selector || !node.placeholder.matches(selector)) | 
|  | 239     ) | 
|  | 240     { | 
|  | 241       tbody.replaceChild(node.placeholder, node); | 
|  | 242     } | 
|  | 243   } | 
|  | 244 | 
|  | 245   // if there is a list of nodes to filter | 
|  | 246   if (selector) | 
|  | 247   { | 
|  | 248     // per each of them put a placeholder inside the tbody | 
|  | 249     for (const tr of tbody.querySelectorAll(selector)) | 
|  | 250     { | 
|  | 251       tbody.replaceChild(getPlaceholder(tr), tr); | 
|  | 252     } | 
|  | 253   } | 
|  | 254 } | 
|  | 255 | 
| 193 document.addEventListener("DOMContentLoaded", () => | 256 document.addEventListener("DOMContentLoaded", () => | 
| 194 { | 257 { | 
| 195   let container = document.getElementById("items"); | 258   let container = document.getElementById("items"); | 
| 196   let table = container.querySelector("tbody"); | 259   let table = container.querySelector("tbody"); | 
|  | 260   let bgItems = container.querySelector("#background-items"); | 
| 197   let template = document.querySelector("template").content.firstElementChild; | 261   let template = document.querySelector("template").content.firstElementChild; | 
|  | 262   const records = []; | 
| 198 | 263 | 
| 199   document.getElementById("reload").addEventListener("click", () => | 264   document.getElementById("reload").addEventListener("click", () => | 
| 200   { | 265   { | 
| 201     ext.devtools.inspectedWindow.reload(); | 266     ext.devtools.inspectedWindow.reload(); | 
| 202   }, false); | 267   }, false); | 
| 203 | 268 | 
| 204   document.getElementById("filter-state").addEventListener("change", (event) => | 269   document.getElementById("filter-state").addEventListener("change", (event) => | 
| 205   { | 270   { | 
| 206     container.dataset.filterState = event.target.value; | 271     container.dataset.filterState = event.target.value; | 
|  | 272     updateRows(table, container.dataset); | 
| 207   }, false); | 273   }, false); | 
| 208 | 274 | 
| 209   document.getElementById("filter-type").addEventListener("change", (event) => | 275   document.getElementById("filter-type").addEventListener("change", (event) => | 
| 210   { | 276   { | 
| 211     container.dataset.filterType = event.target.value; | 277     container.dataset.filterType = event.target.value; | 
|  | 278     updateRows(table, container.dataset); | 
| 212   }, false); | 279   }, false); | 
| 213 | 280 | 
| 214   ext.onMessage.addListener((message) => | 281   ext.onMessage.addListener((message) => | 
| 215   { | 282   { | 
| 216     switch (message.type) | 283     switch (message.type) | 
| 217     { | 284     { | 
| 218       case "add-record": | 285       case "add-record": | 
| 219         table.appendChild(createRecord(message.request, message.filter, | 286         let record = createRecord(message.request, message.filter, template); | 
| 220                                        template)); | 287         records.push(record); | 
|  | 288         if (message.request.docDomain == null) | 
|  | 289         { | 
|  | 290           table.appendChild(record); | 
|  | 291         } | 
|  | 292         else | 
|  | 293         { | 
|  | 294           table.insertBefore(record, bgItems); | 
|  | 295         } | 
| 221         break; | 296         break; | 
| 222 | 297 | 
| 223       case "update-record": | 298       case "update-record": | 
| 224         let oldRow = table.getElementsByTagName("tr")[message.index]; | 299         let oldRow = records[message.index]; | 
| 225         let newRow = createRecord(message.request, message.filter, template); | 300         let newRow = createRecord(message.request, message.filter, template); | 
| 226         oldRow.parentNode.replaceChild(newRow, oldRow); | 301         records[message.index] = newRow; | 
|  | 302         let liveRow = oldRow.parentNode ? oldRow : oldRow.placeholder; | 
|  | 303         liveRow.parentNode.replaceChild(newRow, liveRow); | 
| 227         newRow.classList.add("changed"); | 304         newRow.classList.add("changed"); | 
| 228         container.classList.add("has-changes"); | 305         container.classList.add("has-changes"); | 
| 229         break; | 306         break; | 
| 230 | 307 | 
| 231       case "remove-record": | 308       case "remove-record": | 
| 232         let row = table.getElementsByTagName("tr")[message.index]; | 309         let row = records.splice(message.index, 1)[0]; | 
| 233         row.parentNode.removeChild(row); | 310         let live = row.parentNode ? row : row.placeholder; | 
|  | 311         live.parentNode.removeChild(live); | 
| 234         container.classList.add("has-changes"); | 312         container.classList.add("has-changes"); | 
| 235         break; | 313         break; | 
| 236 | 314 | 
| 237       case "reset": | 315       case "reset": | 
|  | 316         records.splice(0); | 
| 238         table.innerHTML = ""; | 317         table.innerHTML = ""; | 
| 239         container.classList.remove("has-changes"); | 318         container.classList.remove("has-changes"); | 
| 240         break; | 319         break; | 
| 241     } | 320     } | 
| 242   }); | 321   }); | 
| 243 | 322 | 
| 244   window.addEventListener("message", (event) => | 323   window.addEventListener("message", (event) => | 
| 245   { | 324   { | 
| 246     switch (event.data.type) | 325     switch (event.data.type) | 
| 247     { | 326     { | 
| 248       case "performSearch": | 327       case "performSearch": | 
| 249         performSearch(table, event.data.queryString); | 328         performSearch(table, event.data.queryString); | 
| 250         lastFilterQuery = event.data.queryString; | 329         lastFilterQuery = event.data.queryString; | 
| 251         break; | 330         break; | 
| 252       case "cancelSearch": | 331       case "cancelSearch": | 
| 253         cancelSearch(table); | 332         cancelSearch(table); | 
| 254         lastFilterQuery = null; | 333         lastFilterQuery = null; | 
| 255         break; | 334         break; | 
| 256     } | 335     } | 
| 257   }); | 336   }); | 
| 258 | 337 | 
| 259   // Since Chrome 54 the themeName is accessible, for earlier versions we must | 338   // Since Chrome 54 the themeName is accessible, for earlier versions we must | 
| 260   // assume the default theme is being used. | 339   // assume the default theme is being used. | 
| 261   // https://bugs.chromium.org/p/chromium/issues/detail?id=608869 | 340   // https://bugs.chromium.org/p/chromium/issues/detail?id=608869 | 
| 262   let theme = browser.devtools.panels.themeName || "default"; | 341   let theme = browser.devtools.panels.themeName || "default"; | 
| 263   document.body.classList.add(theme); | 342   document.body.classList.add(theme); | 
| 264 }, false); | 343 }, false); | 
| OLD | NEW | 
|---|