An interesting question on StackOverflow prompted me to look into creating a universal spy/logger for all Requests that MooTools. The objective is: being able to log / spy on all XHR requests w/o modifying code anywhere.
It is trivial to override the Request Class and change the prototype of the success and failure. The problem is, Request is extended and used by Request.HTML and Request.JSON, who in turn override these methods. So we need something more flexible.
After a LOT of thinking, I eventually came up with this solution, which automates it and gives a nice API:
(function() { // what we will extend var classes = [Request, Request.HTML, Request.JSON], // map to a text name mapper = ["Request", "Request.HTML", "Request.JSON"], // store reference to original methods orig = { onSuccess: Request.prototype.onSuccess, onFailure: Request.prototype.onFailure }, // changes to protos to implement changes = { onSuccess: function(){ Request.Spy && typeof Request.Spy == "function" && Request.Spy.apply(this, arguments); orig.onSuccess.apply(this, arguments); }, onFailure: function(){ Request.Spy && typeof Request.Spy == "function" && Request.Spy.apply(this, arguments); orig.onFailure.apply(this, arguments); } }; // implement our changes object into the classes classes.invoke('implement', changes); // allow us to tell which Class prototype has called the ajax, only needs to go on Request, // the other subclasses will inherit it automatically. Request.implement({ getClass: function() { var ret; Array.each(classes, function(klass, index) { if (instanceOf(this, klass)) { ret = mapper[index]; } }, this); return ret; } }); })(); // to enable spying, just define Request.Spy as a function: Request.Spy = function() { // you can implement a pub/sub system via trivial events here, making requests available to your app at any time. console.log(this.getClass(), arguments); }; // test it via normal Request new Request({ url: "/echo/html/", data: { html: "normal data" } }).send(); // test via HTML new Request.HTML({ url: "/echo/html/", data: { html: "<p>normal data</p>" } }).send(); // test via JSON new Request.JSON({ url: "/echo/json/", data: { json: JSON.encode({'normal':'data'}) } }).send();
You can see it in action in this jsfiddle: http://jsfiddle.net/dimitar/3rnKe/. Hope somebody finds it useful. P.S. strictly speaking, you only need to apply the method to the sub classes if they have their own implementation of onSuccess or onFailure. Else, changing the prototype of Request is enough. To make this universal for any class, you can check via hasOwnProperty and if so, apply, else – skip.
GitHub flavoured markdown enabled.