I'm trying to create 7 Javascript shared workers inside a for loop.
My IDE (Pycharm) is giving me a warning for these two variables container-frame and worker:
"Mutable variable is accessible from closure"
Each of these shared worker is communicating with network_worker.js
Below is my JS code:
socket = io.connect('http://' + document.domain + ':4999/layout');
// Set up CSS
for (var i=0; i<player_dict.length; i++) {
var _id = player_dict[i]['_id'];
var container_frame = document.getElementById("container-frame-" + _id);
container_frame.style.display = "none";
setup_communication();
console.log(_id)
var client_id = _id;
var alarm_flag= "";
var alarm_metric="";
if (client_id != null && client_id == 0 && parseInt(location.port) == 4999) { // player_0_hack (for now). Remove and have work properly.
label = "";
} else if (client_id != null){
label = "Service " + (parseInt(location.port) - 5000 + 1);
} else {
label = "Invalid player id";
}
var worker = new SharedWorker('../static/js/network_worker.js', client_id);
console.log(worker);
worker.port.addEventListener('message', worker_callback, false);
window.addEventListener("beforeunload", function () {
worker.port.postMessage('label_close');
});
worker.port.start();
function worker_callback(e) {
console.log(e.data)
if(e.data.type == "update_label") {
console.log(container_frame)
container_frame.style.animationDuration = Math.random() + "s";
}
}
worker.port.postMessage({type: "label_connection", payload: {domain: document.domain, port: location.port, client_id: client_id, label: label}, alarm_flag: alarm_flag, alarm_rate: 1, alarm_metric: alarm_metric});
}
Ultimately what I'm trying to do is animating the container-frame for 7 HTML elements. I'm iterating over these elements using the for loop. These animations happen when an event is triggered from a JS script (update label).
Currently, I have 7 HTML elements. The last element only is having the animation working properly.
My doubt is that when I have put the worker_callback function inside the for loop, the JS compiler became confused about the scope of container_frame but I'm not sure.
Any suggestions please ?
The problem was the two variables container_frame and worker where defined as var not const. Thanks to #Edmund Lee
Related
I have an .ascx containing javascript and div elements.
I want insert a log statement inside a function for troubleshooting.
May I know how can I achieve it?
Below is my code snippet:
function SaveGroupCheck() {
var isValid = true;
var haveError = false;
var schedule = document.getElementById("<%=ddlExecutionSchedule.ClientID%>").value;
//INSERT LOGGING HERE - Value of 'schedule'//
if (schedule == "Weekly")
{
var xday = document.getElementById("<%=chkSelectDay.ClientID%>");
var checkbox = xday.getElementsByTagName("input");
var counter = 0;
for (var i = 0; i < checkbox.length; i++) {
if (checkbox[i].checked) {
counter++;
}
}
//INSERT LOGGING HERE - Value of 'counter'//
if (counter < 1) {
$("#chkSelectDay").addClass('errorbox');
$("#divSelectDay").addClass('has-error has-feedback');
$("#lblSelectDay").addClass('has-error has-feedback');
haveError = true;
}
else {
$("#chkSelectDay").removeClass('errorbox');
$("#divSelectDay").removeClass('has-error has-feedback');
$("#lblSelectDay").removeClass('has-error has-feedback');
}
}
//INSERT LOGGING HERE - Value of 'haveError'//
Below is a log which I attempted but failed. I will use a try-catch if the error info needs to be provided.
var logFileName = ConfigurationManager.AppSettings["logpath"] + "Debug_" + DateTime.Now.ToString("ddMMyyyy_hhmmss") + ".log";
var itemPerPage = document.getElementById("<%=txtItemsPerPage.ClientID%>").value;
Log(DateTime.Now.ToString("ddMMyyyy_hhmmss") + " - itemPerPage = " + itemPerPage);
*logpath configured in app.config.
Thank you for your time.
To log any javascript variables you can use :
console.log("Hello I'm the variable value");
and open chrome console to see the value.
If you want to send variable value to server you must go to ajax call by calling server method for logging.
I hope that I understood your question.
I'm getting the following error when attempting to get an enumerator for a collection of lists: "Uncaught Error: The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested."
It happens on the line var listEnumerator = lists.getEnumerator(); it seems to me that there is an issue in my attempt to load lists into the client object with context.load(lists);
Here's the portion of my code that's causing the problem. I've marked the place just before the error is thrown.
//____________________________Required function for accessing the host site's info.___________________________________
function getQueryStringParameter(param) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == param) {
return singleParam[1];
}
}
}
//____________________________Begin checking for list_________________________
function checkForList(listToFind, typeOfListToCreateIfTheListIsMissing)
{
var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var hostcontext = new SP.AppContextSite(context, hostUrl);
var hostweb = hostcontext.get_web();
var lists = hostweb.get_lists();
context.load(lists);
context.executeQueryAsync(checkIfListExistsUsingEnumerator(listToFind, lists, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
}
//Failed to get lists for some reason
function onQueryFailed(sender, args) {
alert('We failed to retrieve lists. \n' + args.get_message() + '\n' + args.get_stackTrace());
}
//____________________________Does list exist?____________________________
function checkIfListExistsUsingEnumerator(listToFind, lists, hostweb, typeOfList)
{
var listExists = false;
//!!!!!!!!!!!!!!! ERROR HERE !!!!!!!!!!!!!!!!
var listEnumerator = lists.getEnumerator();
var title;
while (listEnumerator.moveNext())
{
title = listEnumerator.get_current().get_title();
if (title == listToFind)
{
listExists = true;
}
}
if (!listExists)
{
alert("It appears that a required list does not already exist. \nClick ok, and we'll automatically create one for you.");
//Create a new list
createList(listToFind, hostweb, typeOfList);
}
else if (listExists)
{
//Do nothing.
}
}
//____________________________If it doesn't, create one on the local site____________________________
function createList(nameOfNewList, hostweb, typeOfList) {
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(nameOfNewList);
if (typeOfList === "events")
{
listCreationInfo.set_templateType(SP.ListTemplateType.events);
}
else if (typeOfList === "contacts")
{
listCreationInfo.set_templateType(SP.ListTemplateType.contacts);
}
var lists = hostweb.get_lists();
var newList = lists.add(listCreationInfo);
context.load(newList);
context.executeQueryAsync(onListCreationSuccess, onListCreationFail);
}
function onListCreationSuccess() {
alert('List created successfully!');
}
function onListCreationFail(sender, args) {
alert('Failed to create the list. ' + args.get_message());
}
I've looked at this question sharepoint javascript collection not initialized error which seems to be fairly similar to mine, but I'm having trouble implementing the solution provided there, making me think my error may be have a different cause.
I've also tried querying for the lists inside of the function that is throwing the error, but that doesn't seem to solve anything.
For a little background, these functions are attempting to read all lists from the app's host site, check to see if a specified list exists, and create a list if no matching list exists. If there's a better way of doing that than what I'm attempting, I'd be open to that too.
Any pointers?
Some things I've tried that don't seem to work:
Changing the Asynchronous query
context.executeQueryAsync(checkIfListExists(listToFind, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
to a Synchronous one.
context.executeQuery(checkIfListExists(listToFind, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
I've figured out an alternate, and shorter way to method of achieving the same goal I was trying to achieve before.
Instead of checking to see if a list does not already exist, I just try to create a list, and the Query fails to create a list if one is already there. (That's good because I don't want to overwrite the list if it is already there.)
I'm not totally sure if there are any undesired side effects of what I'm doing here, but in my tests it produced the desired behavior.
//____________________________Required function for accessing the host site's info.___________________________________
function getQueryStringParameter(param) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == param) {
return singleParam[1];
}
}
}
//____________________________Create a list if one does not already exist_________________________
function createList(listToCreate, typeOfList)
{
// Create an announcement SharePoint list with the name that the user specifies.
var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var hostContext = new SP.AppContextSite(currentContext, hostUrl);
var hostweb = hostContext.get_web();
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(listToCreate);
if (typeOfList === "events")
{
listCreationInfo.set_templateType(SP.ListTemplateType.events);
}
else if (typeOfList === "contacts")
{
listCreationInfo.set_templateType(SP.ListTemplateType.contacts);
}
var lists = hostweb.get_lists();
var newList = lists.add(listCreationInfo);
currentContext.load(newList);
currentContext.executeQueryAsync(onListCreationSuccess, onListCreationFail);
}
function onListCreationSuccess() {
alert("We've created a list since one doesn't exist yet." );
}
function onListCreationFail(sender, args) {
alert("We didn't create the list. Here's why: " + args.get_message());
}
I have a table called Subscription and another table called Client I need the gender of the Client who owns the subscription every time I make an update. Here's my update script:
function update(item, user, request) {
var subscriptionId = item.id;
var subscriptionActivitiesTable = tables.getTable("SubscriptionActivity");
var userTable = tables.getTable("User");
var activityTable = tables.getTable("Activity");
var userGender = userTable.where({id: item.UserId}).select('Gender').take(1).read();
console.log(userGender);
activityTable.where({PlanId:item.PlanId, Difficulty: item.Difficulty}).read({
success: function(results){
var startDate = item.StartDate;
results.forEach(function(activity)
{
var testDate = new Date(startDate.getFullYear(),startDate.getMonth(), startDate.getDate());
testDate.setDate(testDate.getDate() + activity.Sequence + (activity.Week*7));
subscriptionActivitiesTable.insert({SubscriptionId: subscriptionId,
ActivityId: activity.id, ShowDate: new Date(testDate.getFullYear(),
testDate.getMonth(), testDate.getDate()), CreationDate: new Date()});
})
}
});
var planWeeks = 12;//VER DE DONDE SACAMOS ESTE NUMERO
var idealWeight = 0;
if (userGender === "Male")
{
idealWeight = (21.7 * Math.pow(parseInt(item.Height)/100,2));
}
else
{
idealWeight = (23 * Math.pow(parseInt(item.Height)/100,2));
}
var metabolismoBasal = idealWeight * 0.95 * 24;
var ADE = 0.1 * metabolismoBasal;
var activityFactor;
if (item.Difficulty === "Easy")
{
activityFactor = 1.25;
}
else if(item.Difficulty === "Medium")
{
activityFactor = 1.5;
}
else
{
activityFactor = 1.75;
}
var caloricRequirement = ((metabolismoBasal + ADE)*activityFactor);
activityTable.where(function(item, caloricRequirement){
return this.PlanId === item.PlanId && this.Type != "Sport" &&
this.CaloricRequirementMin <= caloricRequirement &&
this.CaloricRequirementMax >= caloricRequirement;}, item, caloricRequirement).read({
success: function(results)
{
var startDate = item.StartDate;
results.forEach(function(activity)
{
for (var i=0;i<planWeeks;i++)
{
var testDate = new Date(startDate.getFullYear(),startDate.getMonth(), startDate.getDate());
testDate.setDate(testDate.getDate() + activity.Sequence + (i*7));
subscriptionActivitiesTable.insert({SubscriptionId: subscriptionId,
ActivityId: activity.id, ShowDate: new Date(testDate.getFullYear(),
testDate.getMonth(), testDate.getDate()), CreationDate: new Date()});
}
})
}
})
request.execute();
}
I tried the code above and clientGender is undefined. As you can see I want to use the gender to set the idealWeight.
The read() method expects a function to be passed in on the success parameter - it doesn't return the result of the query like you'd think.
Try something like this instead:
function update(item, user, request) {
var clientTable = tables.getTable("Client");
var clientGender = 'DEFAULT';
clientTable.where({id: item.ClientId}).select('Gender').take(1).read({
success: function(clients) {
if (clients.length == 0) {
console.error('Unable to find client for id ' + item.ClientId);
} else {
var client = client[0];
clientGender = client.Gender;
// since we're inside the success function, we can continue to
// use the clientGender as it will reflect the correct value
// as retrieved from the database
console.log('INSIDE: ' + clientGender);
}
}
});
// this is going to get called while the clientTable query above is
// still running and will most likely show a value of DEFAULT
console.log('OUTSIDE: ' + clientGender);
}
In this sample, the client table query is kicked off, with a callback function provided in the success parameter. When the query is finished, the callback function is called, and the resulting data is displayed to the log. Meanwhile - while the query is still running, that is - the next statement after the where/take/select/read fluent code is run, another console.log statment is executed to show the value of the clientGender field outside the read function. This code will run while the read statement is still waiting on the database. Your output should look something like this in the WAMS log:
* INSIDE: Male
* OUTSIDE: Default
Since the log shows the oldest entries at the bottom, you can see that the OUTSIDE log entry was written sometime before the INSIDE log.
If you're not used to async or functional programming, this might look weird, but as far as I've found, this is now node works. Functions nested in functions nested in functions can get kind of scary, but if you plan ahead, it probably won't be too bad :-)
I've written a Google apps script which first creates and displays a line chart within the UI app and then re-draws the graph based on selected list box values using a Click-button event handler to trigger when the graph "refreshes".
The issue I'm trying to resolve is that when published as a web application when triggering the click event I receive:
Error Encountered: An unexpected error occurred
The code runs perfectly from a spreadsheet (except for some pesky permissions issues where other users are asked to download the panel object; I'll get to that later), and I'm really stuck as to why it won't translate.
Here's the code for what it's worth:
function doGet(){
var app = UiApp.createApplication().setWidth(800).setHeight(650).setTitle('FLEET Chart');
var e = 'undefined';
lb(app);
return click(e, app);
}
function lb(app){
var lb = app.createListBox(true).setId('myId').setName('myLbName');// add items to ListBox
var lb2 = app.createListBox(true).setId('myId2').setName('myLbName2');
var lb3 = app.createListBox(true).setId('myId3').setName('myLbName3');
var bttn = app.createButton('Refresh').setId('myBttn');
lb3.addItem('2011').addItem('2012');
lb2.addItem('January')
.addItem('February')
.addItem('March')
.addItem('April')
.addItem('May')
.addItem('June')
.addItem('July')
.addItem('August')
.addItem('September')
.addItem('October')
.addItem('November')
.addItem('December');
lb.addItem('Drug1')
.addItem('Drug2')
.addItem('Drug3')
.addItem('Drug4');
var mypanel = app.createHorizontalPanel().setVisible(true);
mypanel.add(lb).add(lb2).add(lb3).add(bttn);
app.add(mypanel);
var handler = app.createServerChangeHandler('click').addCallbackElement(mypanel);
handler.addCallbackElement(bttn);
bttn.addClickHandler(handler);
}
function click(e, app) {
var valuelb = new Array('Drug1','Drug2','Drug3','Drug4');
var valuelb2 = new Array ('January','February','March','April','May','June','July','August','September','October','November','December');
var valuelb3 = new Array('2011','2012');
var SS = SpreadsheetApp.openById('0Am8DRqAEaxH7dF9NWFJLSTdWZGRxeEFfMkFjNlFCT2c');
var sheeteff = SS.getSheetByName('Efficiency');
var data = sheeteff.getDataRange().getValues();
if (String(e) != 'undefined') {
app.setWidth(800).setHeight(650).setTitle('FLEET Chart');
var valuelb = String(e.parameter.myLbName);
if (valuelb.indexOf(',') != -1) {
var valuelb = e.parameter.myLbName.split(',');
}
var valuelb2 = String(e.parameter.myLbName2);
if (valuelb2.indexOf(',') != -1) {
var valuelb2 = e.parameter.myLbName2.split(',');
}
var valuelb3 = String(e.parameter.myLbName3);
if (valuelb3.indexOf(',') != -1) {
var valuelb3 = e.parameter.myLbName3.split(',');
}
SS.getSheetByName('Sheet2').getRange(1,1).setValue(String(valuelb2) + ' ' + valuelb.indexOf(','));//for unformation purposes
lb(app);
}else{
SS.getSheetByName('Sheet2').getRange(1,1).setValue(String(e));//for information purposes
}
var usedata = ArrayLib.filterByText(ArrayLib.filterByText(ArrayLib.filterByText(data, 3, valuelb), 1, valuelb2), 0, valuelb3);
//Build data table
var dataTable = Charts.newDataTable();
//Add Column types
dataTable.addColumn(Charts.ColumnType.DATE, data[0][2]);
dataTable.addColumn(Charts.ColumnType.NUMBER, data[0][9]);
dataTable.addColumn(Charts.ColumnType.NUMBER, data[0][8]);
//Add rows
for(var j=0; j<usedata.length; j++){
dataTable.setValue(j, 0, usedata[j][2]);
dataTable.setValue(j, 1, usedata[j][9]);
dataTable.setValue(j, 2, usedata[j][8]);
}
//Create and build chart
var chart = Charts.newLineChart()
.setDataTable(dataTable)
.setTitle('Efficiency over Time \nConfiguration: [' + valuelb + ']\n' + 'Month: [' + valuelb2 + ']\n' + 'Year: [' + valuelb3 + ']')
.setXAxisTitle('Time')
.setYAxisTitle('Percentage')
.setDimensions(750, 600)
.setPointStyle(Charts.PointStyle.MEDIUM)
.build();
app.add(chart);
return app;
}
I've not gone through your entire code but definitely see this wrong - you have set doGet as the function to be called on a handler. No problems with that except you try to call UiApp.createApplication() for the second time which isn't allowed.
I suggest you change the handler to call another function (lb, maybe) instead of doGet.
I also have "Unexpected Errors" in my code. To fix them, I wrote a simple library which helps to find problems in server handlers. Here is an example demonstrating how to use the library. The example source code is here. To add the library to a script is necessary to use the Mr6TKHuVEJGjYr-NnLUNbEkFO7CoOZA03 project key in the Resources->Manage Libraries dialog. The library uses the ScriptProperties Service to store own internal variables.
Update: I guess the subject gave a wrong notion that I'm looking for an existing addon. This is a custom problem and I do NOT want an existing solution.
I wish to WRITE (or more appropriately, modify and existing) Addon.
Here's my requirement:
I want my addon to work for a particular site only
The data on the pages are encoded using a 2 way hash
A good deal of info is loaded by XHR requests, and sometimes
displayed in animated bubbles etc.
The current version of my addon parses the page via XPath
expressions, decodes the data, and replaces them
The issue comes in with those bubblified boxes that are displayed
on mouse-over event
Thus, I realized that it might be a good idea to create an XHR
bridge that could listen to all the data and decode/encode on the fly
After a couple of searches, I came across nsITraceableInterface[1][2][3]
Just wanted to know if I am on the correct path. If "yes", then kindly
provide any extra pointers and suggestions that may be appropriate;
and if "No", then.. well, please help with correct pointers :)
Thanks,
Bipin.
[1]. https://developer.mozilla.org/en/NsITraceableChannel
[2]. http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
[3]. http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/
nsITraceableChannel is indeed the way to go here. the blog posts by Jan Odvarko (softwareishard.com) and myself (ashita.org) show how to do this. You may also want to see http://www.ashita.org/implementing-an-xpcom-firefox-interface-and-creating-observers/, however it isn't really necessary to do this in an XPCOM component.
The steps are basically:
Create Object prototype implementing nsITraceableChannel; and create observer to listen to http-on-modify-request and http-on-examine-response
register observer
observer listening to the two request types adds our nsITraceableChannel object into the chain of listeners and make sure that our nsITC knows who is next in the chain
nsITC object provides three callbacks and each will be called at the appropriate stage: onStartRequest, onDataAvailable, and onStopRequest
in each of the callbacks above, our nsITC object must pass on the data to the next item in the chain
Below is actual code from a site-specific add-on I wrote that behaves very similarly to yours from what I can tell.
function TracingListener() {
//this.receivedData = [];
}
TracingListener.prototype =
{
originalListener: null,
receivedData: null, // array for incoming data.
onDataAvailable: function(request, context, inputStream, offset, count)
{
var binaryInputStream = CCIN("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
var storageStream = CCIN("#mozilla.org/storagestream;1", "nsIStorageStream");
binaryInputStream.setInputStream(inputStream);
storageStream.init(8192, count, null);
var binaryOutputStream = CCIN("#mozilla.org/binaryoutputstream;1",
"nsIBinaryOutputStream");
binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
// Copy received data as they come.
var data = binaryInputStream.readBytes(count);
//var data = inputStream.readBytes(count);
this.receivedData.push(data);
binaryOutputStream.writeBytes(data, count);
this.originalListener.onDataAvailable(request, context,storageStream.newInputStream(0), offset, count);
},
onStartRequest: function(request, context) {
this.receivedData = [];
this.originalListener.onStartRequest(request, context);
},
onStopRequest: function(request, context, statusCode)
{
try
{
request.QueryInterface(Ci.nsIHttpChannel);
if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0)
{
var data = null;
if (request.requestMethod.toLowerCase() == "post")
{
var postText = this.readPostTextFromRequest(request, context);
if (postText)
data = ((String)(postText)).parseQuery();
}
var date = Date.parse(request.getResponseHeader("Date"));
var responseSource = this.receivedData.join('');
//fix leading spaces bug
responseSource = responseSource.replace(/^\s+(\S[\s\S]+)/, "$1");
piratequesting.ProcessRawResponse(request.originalURI.spec, responseSource, date, data);
}
}
catch (e)
{
dumpError(e);
}
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
readPostTextFromRequest : function(request, context) {
try
{
var is = request.QueryInterface(Ci.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Ci.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
}
// Read data from the stream..
var charset = "UTF-8";
var text = this.readFromStream(is, charset, true);
// Seek locks the file so, seek to the beginning only if necko hasn't read it yet,
// since necko doesn't seek to 0 before reading (at lest not till 459384 is fixed).
if (ss && prevOffset == 0)
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
dump("Failed to Query Interface for upload stream.\n");
}
}
catch(exc)
{
dumpError(exc);
}
return null;
},
readFromStream : function(stream, charset, noClose) {
var sis = CCSV("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
sis.setInputStream(stream);
var segments = [];
for (var count = stream.available(); count; count = stream.available())
segments.push(sis.readBytes(count));
if (!noClose)
sis.close();
var text = segments.join("");
return text;
}
}
hRO = {
observe: function(request, aTopic, aData){
try {
if (typeof Cc == "undefined") {
var Cc = Components.classes;
}
if (typeof Ci == "undefined") {
var Ci = Components.interfaces;
}
if (aTopic == "http-on-examine-response") {
request.QueryInterface(Ci.nsIHttpChannel);
if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0) {
var newListener = new TracingListener();
request.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = request.setNewListener(newListener);
}
}
} catch (e) {
dump("\nhRO error: \n\tMessage: " + e.message + "\n\tFile: " + e.fileName + " line: " + e.lineNumber + "\n");
}
},
QueryInterface: function(aIID){
if (typeof Cc == "undefined") {
var Cc = Components.classes;
}
if (typeof Ci == "undefined") {
var Ci = Components.interfaces;
}
if (aIID.equals(Ci.nsIObserver) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
};
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(hRO,
"http-on-examine-response", false);
In the above code, originalListener is the listener we are inserting ourselves before in the chain. It is vital that you keep that info when creating the Tracing Listener and pass on the data in all three callbacks. Otherwise nothing will work (pages won't even load. Firefox itself is last in the chain).
Note: there are some functions called in the code above which are part of the piratequesting add-on, e.g.: parseQuery() and dumpError()
Tamper Data Add-on. See also the How to Use it page
You could try making a Greasemonkey script and overwriting the XMLHttpRequest.
The code would look something like:
function request () {
};
request.prototype.open = function (type, path, block) {
GM_xmlhttpRequest({
method: type,
url: path,
onload: function (response) {
// some code here
}
});
};
unsafeWindow.XMLHttpRequest = request;
Also note that you can turn a GM script into an addon for Firefox.