| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This Source Code is subject to the terms of the Mozilla Public License | 2  * This Source Code is subject to the terms of the Mozilla Public License | 
| 3  * version 2.0 (the "License"). You can obtain a copy of the License at | 3  * version 2.0 (the "License"). You can obtain a copy of the License at | 
| 4  * http://mozilla.org/MPL/2.0/. | 4  * http://mozilla.org/MPL/2.0/. | 
| 5  */ | 5  */ | 
| 6 | 6 | 
| 7 const Cc = Components.classes; | 7 const Cc = Components.classes; | 
| 8 const Ci = Components.interfaces; | 8 const Ci = Components.interfaces; | 
| 9 const Cr = Components.results; | 9 const Cr = Components.results; | 
| 10 const Cu = Components.utils; | 10 const Cu = Components.utils; | 
| 11 | 11 | 
| 12 Cu.import("resource://gre/modules/Services.jsm"); | 12 Cu.import("resource://gre/modules/Services.jsm"); | 
| 13 | 13 | 
| 14 function abprequire(module) | 14 function abprequire(module) | 
| 15 { | 15 { | 
| 16   let result = {}; | 16   let result = {}; | 
| 17   result.wrappedJSObject = result; | 17   result.wrappedJSObject = result; | 
| 18   Services.obs.notifyObservers(result, "adblockplus-require", module); | 18   Services.obs.notifyObservers(result, "adblockplus-require", module); | 
| 19   return result.exports; | 19   return result.exports; | 
| 20 } | 20 } | 
| 21 | 21 | 
| 22 let {Policy} = abprequire("contentPolicy"); | 22 let {Policy} = abprequire("contentPolicy"); | 
| 23 let {RequestNotifier} = abprequire("requestNotifier"); |  | 
| 24 let {Filter} = abprequire("filterClasses"); | 23 let {Filter} = abprequire("filterClasses"); | 
| 25 | 24 | 
| 26 let policyGlobal = Cu.getGlobalForObject(Policy); | 25 let origShouldAllow = Policy.shouldAllow; | 
| 27 let PolicyPrivate = null; | 26 if (!origShouldAllow) | 
| 28 |  | 
| 29 if ("PolicyImplementation" in policyGlobal)  // ABP 2.1+ with scope separation |  | 
| 30   PolicyPrivate = policyGlobal.PolicyImplementation; |  | 
| 31 else if ("require" in policyGlobal)               // ABP 2.1+ without scope sepa
     ration |  | 
| 32   PolicyPrivate = policyGlobal.require.scopes.contentPolicy.PolicyImplementation
     ; |  | 
| 33 else |  | 
| 34   window.close(); | 27   window.close(); | 
| 35 | 28 | 
| 36 let origShouldLoad = PolicyPrivate.shouldLoad; |  | 
| 37 let origProcessNode = Policy.processNode; |  | 
| 38 |  | 
| 39 let currentData = null; |  | 
| 40 let processingQueue = []; | 29 let processingQueue = []; | 
| 41 let notifier = null; | 30 let notifier = null; | 
| 42 | 31 | 
| 43 // Randomize URI to work around bug 719376 | 32 // Randomize URI to work around bug 719376 | 
| 44 let stringBundle = Services.strings.createBundle("chrome://abpwatcher/locale/glo
     bal.properties?" + Math.random()); | 33 let stringBundle = Services.strings.createBundle("chrome://abpwatcher/locale/glo
     bal.properties?" + Math.random()); | 
| 45 | 34 | 
| 46 let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.
     nsIClipboardHelper); | 35 let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.
     nsIClipboardHelper); | 
| 47 | 36 | 
| 48 function init() | 37 function init() | 
| 49 { | 38 { | 
| 50   let list = document.getElementById("list"); | 39   let list = document.getElementById("list"); | 
| 51   list.view = treeView; | 40   list.view = treeView; | 
| 52   list.focus(); | 41   list.focus(); | 
| 53 | 42 | 
| 54   treeView.addObserver(updateProcessingTime); | 43   treeView.addObserver(updateProcessingTime); | 
| 55   updateProcessingTime(treeView, "refresh"); | 44   updateProcessingTime(treeView, "refresh"); | 
| 56 | 45 | 
| 57   // Make sure the tree view has correct filters | 46   // Make sure the tree view has correct filters | 
| 58   document.getElementById("ignore-early").doCommand(); |  | 
| 59   document.getElementById("filterText").doCommand(); | 47   document.getElementById("filterText").doCommand(); | 
| 60 | 48 | 
| 61   notifier = new RequestNotifier(null, handleFilterHit); | 49   Policy.shouldAllow = replacementShouldAllow; | 
| 62 |  | 
| 63   PolicyPrivate.shouldLoad = replacementShouldLoad; |  | 
| 64   Policy.processNode = replacementProcessNode; |  | 
| 65   setInterval(processQueue, 200); | 50   setInterval(processQueue, 200); | 
| 66 } | 51 } | 
| 67 | 52 | 
| 68 function E(id) | 53 function E(id) | 
| 69 { | 54 { | 
| 70   return document.getElementById(id); | 55   return document.getElementById(id); | 
| 71 } | 56 } | 
| 72 | 57 | 
| 73 function replacementShouldLoad(contentType, contentLocation, requestOrigin, node
     , mimeTypeGuess, extra) | 58 function replacementShouldAllow({contentType, location, frames, isPrivate}) | 
| 74 { | 59 { | 
| 75   let startTime = null; | 60   let startTime = Date.now(); | 
|  | 61   let currentData = { | 
|  | 62     type: contentType, | 
|  | 63     location: location, | 
|  | 64     frames: frames, | 
|  | 65     isPrivate: isPrivate | 
|  | 66   }; | 
|  | 67   let ret; | 
|  | 68 | 
| 76   try | 69   try | 
| 77   { | 70   { | 
| 78     currentData = {internal: false, earlyReturn: true, filters: []}; | 71     ret = origShouldAllow.apply(this, arguments); | 
| 79     startTime = Date.now(); |  | 
| 80 |  | 
| 81     if (contentLocation) |  | 
| 82       currentData.location = contentLocation.spec; |  | 
| 83     if (requestOrigin) |  | 
| 84       currentData.origin = requestOrigin.spec; |  | 
| 85 |  | 
| 86     currentData.type = contentType; |  | 
| 87   } catch(e) {} |  | 
| 88 |  | 
| 89   let ret; |  | 
| 90   try |  | 
| 91   { |  | 
| 92     ret = origShouldLoad.apply(this, arguments); |  | 
| 93     return ret; |  | 
| 94   } |  | 
| 95   finally |  | 
| 96   { |  | 
| 97     if (startTime !== null) |  | 
| 98       currentData.processingTime = (Date.now() - startTime); |  | 
| 99     currentData.result = (ret == Ci.nsIContentPolicy.ACCEPT); |  | 
| 100 |  | 
| 101     processingQueue.push(currentData); |  | 
| 102     currentData = null; |  | 
| 103   } |  | 
| 104 } |  | 
| 105 |  | 
| 106 function replacementProcessNode(wnd, node, contentType, location, collapse) |  | 
| 107 { |  | 
| 108   let startTime = null; |  | 
| 109   try |  | 
| 110   { |  | 
| 111     if (currentData && !("context" in currentData)) |  | 
| 112     { |  | 
| 113       currentData.earlyReturn = false; |  | 
| 114       currentData.context = node; |  | 
| 115       currentData.window = wnd; |  | 
| 116       currentData.internalType = contentType; |  | 
| 117       if (location) |  | 
| 118           currentData.internalLocation = location.spec; |  | 
| 119     } |  | 
| 120     else |  | 
| 121     { |  | 
| 122       // shouldLoad wasn't called - this isn't being called by content policy |  | 
| 123       let locationString = (location instanceof Filter ? location.text : locatio
     n.spec); |  | 
| 124 |  | 
| 125       currentData = { |  | 
| 126         internal: true, |  | 
| 127         earlyReturn: false, |  | 
| 128         filters: [], |  | 
| 129         location: locationString, |  | 
| 130         internalLocation: locationString, |  | 
| 131         context: node, |  | 
| 132         window: wnd, |  | 
| 133         type: contentType, |  | 
| 134         internalType: contentType |  | 
| 135       }; |  | 
| 136       startTime = Date.now(); |  | 
| 137     } |  | 
| 138   } |  | 
| 139   catch(e) |  | 
| 140   { |  | 
| 141     Cu.reportError(e); |  | 
| 142   } |  | 
| 143 |  | 
| 144   let ret; |  | 
| 145   try |  | 
| 146   { |  | 
| 147     ret = origProcessNode.apply(this, arguments); |  | 
| 148     return ret; | 72     return ret; | 
| 149   } | 73   } | 
| 150   finally | 74   finally | 
| 151   { | 75   { | 
| 152     if (startTime !== null) | 76     if (startTime !== null) | 
| 153     { | 77     { | 
| 154       currentData.processingTime = (Date.now() - startTime); | 78       currentData.processingTime = (Date.now() - startTime); | 
| 155       currentData.result = (ret == true); | 79       currentData.result = ret; | 
|  | 80       currentData.filters = ret.hits.filter(h => h.filter).map(h => h.filter); | 
| 156 | 81 | 
| 157       processingQueue.push(currentData); | 82       processingQueue.push(currentData); | 
| 158       currentData = null; | 83       currentData = null; | 
| 159     } | 84     } | 
| 160   } | 85   } | 
| 161 } | 86 } | 
| 162 | 87 | 
| 163 function destroy() | 88 function destroy() | 
| 164 { | 89 { | 
| 165   if (notifier) | 90   if (origShouldAllow) | 
| 166     notifier.shutdown(); | 91     Policy.shouldAllow = origShouldAllow; | 
| 167   if (origShouldLoad) |  | 
| 168     PolicyPrivate.shouldLoad = origShouldLoad; |  | 
| 169   if (origProcessNode) |  | 
| 170     Policy.processNode = origProcessNode; |  | 
| 171 } |  | 
| 172 |  | 
| 173 function handleFilterHit(wnd, node, data) |  | 
| 174 { |  | 
| 175   if (data.filter && currentData) |  | 
| 176     currentData.filters.push(data.filter.text); |  | 
| 177 } | 92 } | 
| 178 | 93 | 
| 179 function processQueue() | 94 function processQueue() | 
| 180 { | 95 { | 
| 181   if (!processingQueue.length) | 96   if (!processingQueue.length) | 
| 182     return; | 97     return; | 
| 183 | 98 | 
|  | 99   function stringify(value) | 
|  | 100   { | 
|  | 101     if (typeof value == "undefined" || value == null) | 
|  | 102       return ""; | 
|  | 103     else | 
|  | 104       return String(value); | 
|  | 105   } | 
|  | 106 | 
| 184   for each (let entry in processingQueue) | 107   for each (let entry in processingQueue) | 
| 185   { | 108   { | 
| 186     entry.cols = {}; | 109     entry.cols = { | 
| 187     if (typeof entry.location != "undefined") | 110       address: stringify(entry.location), | 
| 188       entry.cols.address = String(entry.location); | 111       type: stringify(entry.type), | 
| 189     if (typeof entry.type != "undefined") | 112       result: stringBundle.GetStringFromName(entry.result && entry.result.allow 
     ? "decision.allow" : "decision.block"), | 
| 190     { | 113       origin: stringify(entry.frames && entry.frames[0] && entry.frames[0].locat
     ion), | 
| 191       entry.cols.type = String(entry.type); | 114       filter: stringify(entry.filters && entry.filters.join(", ")), | 
| 192       try { | 115       time: stringify(entry.processingTime) | 
| 193         // Nasty hack: try to get type name from ABP | 116     }; | 
| 194         if (entry.type in Policy.localizedDescr) |  | 
| 195           entry.cols.type = String(Policy.localizedDescr[entry.type]); |  | 
| 196       } catch(e) {} |  | 
| 197     } |  | 
| 198     entry.cols.result = stringBundle.GetStringFromName(entry.result ? "decision.
     allow" : "decision.block"); |  | 
| 199     if (typeof entry.context != "undefined") |  | 
| 200       entry.cols.context = (entry.context ? getNodeLabel(entry.context) : String
     (entry.context)); |  | 
| 201     if (typeof entry.window != "undefined") |  | 
| 202       entry.cols.document = (entry.window ? getNodeLabel(entry.window) : String(
     entry.window)); |  | 
| 203     if (typeof entry.origin != "undefined") |  | 
| 204       entry.cols.origin = String(entry.origin); |  | 
| 205     if (entry.filters.length) |  | 
| 206       entry.cols.filter = entry.filters.join(", "); |  | 
| 207     if (typeof entry.processingTime != "undefined") |  | 
| 208       entry.cols.time = String(entry.processingTime); |  | 
| 209 |  | 
| 210     let additional = []; |  | 
| 211     if (entry.internal) |  | 
| 212       additional.push(stringBundle.GetStringFromName("additional.internalInvocat
     ion")); |  | 
| 213     if (typeof entry.internalType != "undefined" && entry.type != entry.internal
     Type) |  | 
| 214     { |  | 
| 215       let internalType = String(entry.internalType); |  | 
| 216       try { |  | 
| 217         // Nasty hack: try to get type name from ABP |  | 
| 218         if (entry.internalType in Policy.localizedDescr) |  | 
| 219           internalType = String(Policy.localizedDescr[entry.internalType]); |  | 
| 220       } catch(e) {} |  | 
| 221       additional.push(stringBundle.formatStringFromName("additional.typeChanged"
     , [internalType], 1)); |  | 
| 222     } |  | 
| 223     if (typeof entry.internalLocation != "undefined" && entry.location != entry.
     internalLocation) |  | 
| 224       additional.push(stringBundle.formatStringFromName("additional.locationChan
     ged", [String(entry.internalLocation)], 1)); |  | 
| 225 |  | 
| 226     if (additional.length > 0) |  | 
| 227       entry.cols.additional = additional.join(", "); |  | 
| 228 |  | 
| 229     treeView.add(entry); | 117     treeView.add(entry); | 
| 230   } | 118   } | 
| 231 | 119 | 
| 232   processingQueue = []; | 120   processingQueue = []; | 
| 233 } | 121 } | 
| 234 | 122 | 
| 235 function getNodeLabel(node) |  | 
| 236 { |  | 
| 237   try |  | 
| 238   { |  | 
| 239     if (node instanceof Ci.nsIDOMWindow) |  | 
| 240       return stringBundle.formatStringFromName("NodeLabel.window", [node.locatio
     n.href], 1); |  | 
| 241     if (node instanceof Ci.nsIDOMDocument) |  | 
| 242       return stringBundle.formatStringFromName("NodeLabel.document", [node.URL],
      1); |  | 
| 243     else if (node instanceof Ci.nsIDOMXULElement) |  | 
| 244       return stringBundle.formatStringFromName("NodeLabel.xulElement", [node.tag
     Name], 1); |  | 
| 245     else if (node instanceof Ci.nsIDOMHTMLElement) |  | 
| 246       return stringBundle.formatStringFromName("NodeLabel.htmlElement", [node.ta
     gName], 1); |  | 
| 247     else if (node instanceof Ci.nsIDOMSVGElement) |  | 
| 248       return stringBundle.formatStringFromName("NodeLabel.svgElement", [node.tag
     Name], 1); |  | 
| 249     else if (node instanceof Ci.nsIDOMElement) |  | 
| 250       return stringBundle.formatStringFromName("NodeLabel.element", [node.tagNam
     e], 1); |  | 
| 251     else |  | 
| 252       return stringBundle.formatStringFromName("NodeLabel.unknown", [String(node
     )], 1); |  | 
| 253   } |  | 
| 254   catch (e) |  | 
| 255   { |  | 
| 256     Cu.reportError(e); |  | 
| 257     return stringBundle.formatStringFromName("NodeLabel.unknown", [""], 1); |  | 
| 258   } |  | 
| 259 } |  | 
| 260 |  | 
| 261 function fillInTooltip(event) | 123 function fillInTooltip(event) | 
| 262 { | 124 { | 
| 263   let entry = treeView.getEntryAt(event.clientX, event.clientY); | 125   let entry = treeView.getEntryAt(event.clientX, event.clientY); | 
| 264   if (!entry) | 126   if (!entry) | 
| 265     return false; | 127     return false; | 
| 266 | 128 | 
| 267   let rows = document.getElementById("tooltip-rows"); | 129   let rows = document.getElementById("tooltip-rows"); | 
| 268   while (rows.firstChild) | 130   while (rows.firstChild) | 
| 269     rows.removeChild(rows.firstChild); | 131     rows.removeChild(rows.firstChild); | 
| 270 | 132 | 
| 271   let cols = document.getElementById("list").getElementsByTagName("treecol"); | 133   let cols = document.getElementById("list").getElementsByTagName("treecol"); | 
| 272   for (let i = 0; i < cols.length; i++) | 134   for (let i = 0; i < cols.length; i++) | 
| 273   { | 135   { | 
| 274     let col = cols[i].id; | 136     let col = cols[i].id; | 
| 275     if (col && col in entry.cols) | 137     if (col && col in entry.cols) | 
| 276     { | 138     { | 
| 277       let row = document.createElement("row"); | 139       let row = document.createElement("row"); | 
| 278 | 140 | 
| 279       let label = document.createElement("description"); | 141       let label = document.createElement("description"); | 
| 280       label.setAttribute("class", "tooltip-label"); | 142       label.setAttribute("class", "tooltip-label"); | 
| 281       label.setAttribute("value", cols[i].getAttribute("label")); | 143       label.setAttribute("value", cols[i].getAttribute("label")); | 
| 282       row.appendChild(label); | 144       row.appendChild(label); | 
| 283 | 145 | 
| 284       let value = document.createElement("vbox"); | 146       let value = document.createElement("vbox"); | 
| 285       setMultilineContent(value, entry.cols[col]); | 147       let data = entry.cols[col]; | 
|  | 148       if (col == "origin") | 
|  | 149         data = entry.frames.map(f => f.location).join("\n"); | 
|  | 150       setMultilineContent(value, data); | 
| 286       row.appendChild(value); | 151       row.appendChild(value); | 
| 287 | 152 | 
| 288       rows.appendChild(row); | 153       rows.appendChild(row); | 
| 289     } | 154     } | 
| 290   } | 155   } | 
| 291 | 156 | 
| 292   return true; | 157   return true; | 
| 293 } | 158 } | 
| 294 | 159 | 
| 295 function updateContextMenu(event) | 160 function updateContextMenu(event) | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 310     clipboardHelper.copyString(String(entry.location)); | 175     clipboardHelper.copyString(String(entry.location)); | 
| 311 } | 176 } | 
| 312 | 177 | 
| 313 function copyFilters() | 178 function copyFilters() | 
| 314 { | 179 { | 
| 315   let entry = treeView.getCurrentEntry(); | 180   let entry = treeView.getCurrentEntry(); | 
| 316   if (entry && entry.filters.length) | 181   if (entry && entry.filters.length) | 
| 317     clipboardHelper.copyString(entry.filters.join("\n")); | 182     clipboardHelper.copyString(entry.filters.join("\n")); | 
| 318 } | 183 } | 
| 319 | 184 | 
| 320 function setMultilineContent(box, text) { | 185 function setMultilineContent(box, text) | 
| 321   // The following is sufficient in Gecko 1.9 but Gecko 1.8 fails on multiline | 186 { | 
| 322   // text fields in tooltips | 187   let lines = text.split(/\n+/); | 
| 323   // box.textContent = text.replace(/\S{80}(?=\S)/g, "$& "); | 188   for (let line of lines) | 
| 324 | 189   { | 
| 325   for (let i = 0; i < text.length; i += 80) { |  | 
| 326     let description = document.createElement("description"); | 190     let description = document.createElement("description"); | 
| 327     description.setAttribute("value", text.substr(i, 80)); | 191     description.textContent = line.replace(/\S{80}(?=\S)/g, "$& "); | 
| 328     box.appendChild(description); | 192     box.appendChild(description); | 
| 329   } | 193   } | 
| 330 } | 194 } | 
| 331 | 195 | 
| 332 var totalProcessingTime = 0; | 196 var totalProcessingTime = 0; | 
| 333 function updateProcessingTime(view, operation, entry) | 197 function updateProcessingTime(view, operation, entry) | 
| 334 { | 198 { | 
| 335   if (operation == "add") | 199   if (operation == "add") | 
| 336     totalProcessingTime += entry.processingTime; | 200     totalProcessingTime += entry.processingTime; | 
| 337   else { | 201   else { | 
| 338     totalProcessingTime = 0; | 202     totalProcessingTime = 0; | 
| 339     for each (let entry in view.displayedItems) | 203     for each (let entry in view.displayedItems) | 
| 340       totalProcessingTime += entry.processingTime; | 204       totalProcessingTime += entry.processingTime; | 
| 341   } | 205   } | 
| 342 | 206 | 
| 343   let numItems = view.displayedItems.length; | 207   let numItems = view.displayedItems.length; | 
| 344 | 208 | 
| 345   let summary = document.getElementById("summary"); | 209   let summary = document.getElementById("summary"); | 
| 346   let template = summary.getAttribute("_template"); | 210   let template = summary.getAttribute("_template"); | 
| 347   summary.textContent = template.replace(/\*NUMITEMS\*/g, numItems).replace(/\*T
     IME\*/, (totalProcessingTime / 1000).toFixed(3)); | 211   summary.textContent = template.replace(/\*NUMITEMS\*/g, numItems).replace(/\*T
     IME\*/, (totalProcessingTime / 1000).toFixed(3)); | 
| 348 } | 212 } | 
| 349 | 213 | 
| 350 var treeView = { | 214 var treeView = { | 
| 351   currentItems: [], | 215   currentItems: [], | 
| 352   displayedItems: [], | 216   displayedItems: [], | 
| 353   _ignoreEarlyReturns: false, |  | 
| 354   _filterString: "", | 217   _filterString: "", | 
| 355   _sortColumn: null, | 218   _sortColumn: null, | 
| 356   _sortDirection: null, | 219   _sortDirection: null, | 
| 357   boxObject: null, | 220   boxObject: null, | 
| 358   atoms: {}, | 221   atoms: {}, | 
| 359   observers: [], | 222   observers: [], | 
| 360 | 223 | 
| 361   // | 224   // | 
| 362   // nsISupports implementation | 225   // nsISupports implementation | 
| 363   // | 226   // | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 379   selection: null, | 242   selection: null, | 
| 380 | 243 | 
| 381   setTree: function(boxObject) | 244   setTree: function(boxObject) | 
| 382   { | 245   { | 
| 383     if (!boxObject) | 246     if (!boxObject) | 
| 384       return; | 247       return; | 
| 385 | 248 | 
| 386     this.boxObject = boxObject; | 249     this.boxObject = boxObject; | 
| 387 | 250 | 
| 388     let atomService = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomSer
     vice); | 251     let atomService = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomSer
     vice); | 
| 389     for each (let col in ["address", "type", "result", "context", "document", "o
     rigin", "additional", "filter", "time"]) | 252     for each (let col in ["address", "type", "result", "origin", "filter", "time
     "]) | 
| 390     { | 253     { | 
| 391       let atomStr = "col-" + col; | 254       let atomStr = "col-" + col; | 
| 392       this.atoms[atomStr] = atomService.getAtom(atomStr); | 255       this.atoms[atomStr] = atomService.getAtom(atomStr); | 
| 393     } | 256     } | 
| 394     for each (let flag in ["selected", "blocked"]) | 257     for each (let flag in ["selected", "blocked"]) | 
| 395     { | 258     { | 
| 396       let atomStr = flag + "-true"; | 259       let atomStr = flag + "-true"; | 
| 397       this.atoms[atomStr] = atomService.getAtom(atomStr); | 260       this.atoms[atomStr] = atomService.getAtom(atomStr); | 
| 398 | 261 | 
| 399       atomStr = flag + "-false"; | 262       atomStr = flag + "-false"; | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 454   }, | 317   }, | 
| 455 | 318 | 
| 456   getRowProperties: function(row, properties) | 319   getRowProperties: function(row, properties) | 
| 457   { | 320   { | 
| 458     if (row < 0 || row >= this.displayedItems.length) | 321     if (row < 0 || row >= this.displayedItems.length) | 
| 459       return ""; | 322       return ""; | 
| 460 | 323 | 
| 461     let entry = this.displayedItems[row]; | 324     let entry = this.displayedItems[row]; | 
| 462     return this.generateProperties([ | 325     return this.generateProperties([ | 
| 463         "selected-" + this.selection.isSelected(row), | 326         "selected-" + this.selection.isSelected(row), | 
| 464         "blocked-" + !entry.result | 327         "blocked-" + !(entry.result && entry.result.allow) | 
| 465       ], properties); | 328       ], properties); | 
| 466   }, | 329   }, | 
| 467 | 330 | 
| 468   getCellProperties: function(row, col, properties) | 331   getCellProperties: function(row, col, properties) | 
| 469   { | 332   { | 
| 470     return this.getRowProperties(row, properties) + " " + this.getColumnProperti
     es(col, properties); | 333     return this.getRowProperties(row, properties) + " " + this.getColumnProperti
     es(col, properties); | 
| 471   }, | 334   }, | 
| 472 | 335 | 
| 473   cycleHeader: function(col) | 336   cycleHeader: function(col) | 
| 474   { | 337   { | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 524   cycleCell: function() {}, | 387   cycleCell: function() {}, | 
| 525   performAction: function() {}, | 388   performAction: function() {}, | 
| 526   performActionOnRow: function() {}, | 389   performActionOnRow: function() {}, | 
| 527   performActionOnCell: function() {}, | 390   performActionOnCell: function() {}, | 
| 528   selectionChanged: function() {}, | 391   selectionChanged: function() {}, | 
| 529 | 392 | 
| 530   // | 393   // | 
| 531   // Custom methods | 394   // Custom methods | 
| 532   // | 395   // | 
| 533 | 396 | 
| 534   get ignoreEarlyReturns() |  | 
| 535   { |  | 
| 536     return this._ignoreEarlyReturns; |  | 
| 537   }, |  | 
| 538   set ignoreEarlyReturns(value) |  | 
| 539   { |  | 
| 540     this._ignoreEarlyReturns = value; |  | 
| 541     this.refilter(); |  | 
| 542   }, |  | 
| 543 |  | 
| 544   get filterString() | 397   get filterString() | 
| 545   { | 398   { | 
| 546     return this._filterString; | 399     return this._filterString; | 
| 547   }, | 400   }, | 
| 548   set filterString(value) | 401   set filterString(value) | 
| 549   { | 402   { | 
| 550     this._filterString = value.toLowerCase(); | 403     this._filterString = value.toLowerCase(); | 
| 551     this.refilter(); | 404     this.refilter(); | 
| 552   }, | 405   }, | 
| 553 | 406 | 
| 554   filter: function(entry) | 407   filter: function(entry) | 
| 555   { | 408   { | 
| 556     if (this._ignoreEarlyReturns && entry.earlyReturn) |  | 
| 557       return false; |  | 
| 558 |  | 
| 559     if (this._filterString) | 409     if (this._filterString) | 
| 560     { | 410     { | 
| 561       let foundMatch = false; | 411       let foundMatch = false; | 
| 562       for each (let label in entry.cols) | 412       for each (let label in entry.cols) | 
| 563         if (label.toLowerCase().indexOf(this._filterString) >= 0) | 413         if (label.toLowerCase().indexOf(this._filterString) >= 0) | 
| 564           foundMatch = true; | 414           foundMatch = true; | 
| 565 | 415 | 
| 566       if (!foundMatch) | 416       if (!foundMatch) | 
| 567         return false; | 417         return false; | 
| 568     } | 418     } | 
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 678     for (let i = 0; i < this.observers.length; i++) | 528     for (let i = 0; i < this.observers.length; i++) | 
| 679       if (this.observers[i] == observer) | 529       if (this.observers[i] == observer) | 
| 680         this.observers.splice(i--, 1); | 530         this.observers.splice(i--, 1); | 
| 681   }, | 531   }, | 
| 682   notifyObservers: function(operation, entry) | 532   notifyObservers: function(operation, entry) | 
| 683   { | 533   { | 
| 684     for each (let observer in this.observers) | 534     for each (let observer in this.observers) | 
| 685       observer(this, operation, entry); | 535       observer(this, operation, entry); | 
| 686   } | 536   } | 
| 687 }; | 537 }; | 
| OLD | NEW | 
|---|