[Ajax] Hacking Rojo - an Ajax Wrapper for Rojo
Rojo is a great web-based RSS reader. It supports tagging not only feeds but also article entries. The user interface is neat and well organized. The use of DHTML and CSS makes the site easier reading and more accessible.
As we already knew, Rojo uses a lot of DHTML + Javascript techniques to enhance the user interface. Despite Rojo has the modern design of tagging and social share, it seems not to be an Ajax approach I talked in my previous post, "Hacking Rojo - Rojo is not Ajax? ". Rojo retrieve asynchronous data by remote scripting with iframe, not by calling XMLHttpRequest. There would be a little bit slower when using remote script instead of XMLHttpRequest. Therefore I did a small experiment to replace the iframe remote script by the Ajax way. The Greasemonkey user script can meet my need to override the methods of Remote object in Rojo.
This Greasemonkey user script is a wrapper for Rojo to replace its iframe request by the XMLHttpRequest function. The data retrivial will proceed in background, so the browser won't be seen in loading pages any more. After installing the script, the response of using Rojo should become faster.
Download: rojo.ajax.user.js
Let's take a look at the two original methods of Remote object.
Remote.execRequest = function(resource, callback, callbackArguments) {
//NOTE: we need to prevent corruption here due to multi-threaded IO and
//non-blocking UI controls in IE/Mozilla
this.callback = callback;
this.callbackArguments = callbackArguments;
this.waitingForResponse = true;
this.changeIFrameLocation(resource);
}
Remote.iFrameOnLoad = function() {
if ( this.callback != null ) {
var currentCallback = this.callback;
var currentCallbackArguments = this.callbackArguments;
this.callback = null;
this.callbackArguments = null;
this.resource = null;
this.waitingForResponse = false;
if (this.requests.length > 0) {
var nextRequest = Util.shift(this.requests);
this.waitingForResponse = true;
this.execRequest(nextRequest.resource, nextRequest.callback,
nextRequest.callbackArguments);
}
var iframeContents = Remote.getIFrameContents();
if (currentCallbackArguments == undefined ||
currentCallbackArguments == null) {
currentCallbackArguments = new Array();
}
currentCallbackArguments[currentCallbackArguments.length] = iframeContents;
currentCallback.apply(null, currentCallbackArguments);
}
}
Now we can override the above two methods by the following new methods with a real Ajax XMLHttpRequest call.
Remote.fakeiFrameOnLoad = function(result) {
if ( this.callback != null ) {
var currentCallback = this.callback;
var currentCallbackArguments = this.callbackArguments;
this.callback = null;
this.callbackArguments = null;
this.resource = null;
this.waitingForResponse = false;
if (this.requests.length > 0) {
var nextRequest = Util.shift(this.requests);
this.waitingForResponse = true;
this.execRequest(nextRequest.resource, nextRequest.callback, nextRequest.callbackArguments);
}
var iframeContents = result;
if (currentCallbackArguments == undefined || currentCallbackArguments == null) {
currentCallbackArguments = new Array();
}
currentCallbackArguments[currentCallbackArguments.length] = iframeContents;
currentCallback.apply(null, currentCallbackArguments);
}
}
Remote.execRequest = function(resource, callback, callbackArguments) {
this.callback = callback;
this.callbackArguments = callbackArguments;
this.waitingForResponse = true;
// this.changeIFrameLocation(resource);
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState==4) {
if (xmlhttp.status==200) Remote.fakeiFrameOnLoad(xmlhttp.responseText);
}
}
xmlhttp.open('GET', resource, true);
xmlhttp.send(null);
}
