HTML, CSS, JS and other unsorted stuff

tapping XMLHttpRequests

, ,

Since Google (instant and images) and Bing (image search) changed the display of their search engine results, some of my private userJavaScripts stopped working as soon as one of these pages reloaded some new content. The scripts couldn't recognize, that the pages were changed. I tried everything what my small JavaScript knowledge allowed, but nothing worked. The problem irked me for months (but only a few hours per month bigsmile). Finally I got a really good hint from a person, who wants to stay anonymous, that it is possible to overwrite the prototype of the XMLHttpRequest.

Q: OK, but wouldn't pages, that rely heavily on it (like Google Instant), break by overwriting the XMLHttpRequest?

A: Yes, if you do it the wrong way.

It took me some reading to find a nice method called .apply() which allows to adjust the scope of your own calls (if I understood it right, corrections to my clumsy explanations are welcome) and that was the solution for me.

This is a small userJS that displays the request mode, what is sent as request and what is the actual readyState of the request:
// ==UserScript== 
// @name tap XMLHttpRequest
// @include http://*
// @include https://*
/* 
Anstatt die Ergebnisse in der Fehlerkonsole auszugeben, können auch eigene Funktionen aufgerufen werden, z.B. um geänderte Seiten zu bearbeiten. Wahrscheinlich ist ein setTimeout() oder setInterval() mit Nachtriggerung erforderlich, wenn man z.B. Suchergebnisse von Google Instant oder der Bing Bildersuche bearbeiten will, da diese Seiten manchmal ziemlich viele Requests nacheinander abfeuern ... 

Instead of displaying the results in the error console, you can also a call your own functions i.e. to edit changed pages. Possibly a re-triggerable setTimeout() or setInterval() is required, if you want to use this i.e. for processing th search results at Google instant or Bing image search, since they are firing the quite many requests in rapid succession sometimes ...
*/
// ==/UserScript== 

(function(){
	var open = window.XMLHttpRequest.prototype.open,
		send = window.XMLHttpRequest.prototype.send,
		onReadyStateChange;

	function openAugmented(method, url, async, user, password) {
		var syncMode = async !== false ? 'async' : 'sync';
		/* place your function call here */
		opera.postError(
			'Modus ' +
			syncMode +
			' HTTP Anfrage : ' +
			method +
			' ' +
			url
		);
		return open.apply(this, arguments);
	}

	function sendAugmented(data) {
		/* place your function call here */
		opera.postError('Sende HTTP-Anfrage-Daten : ', data);

		if(this.onreadystatechange) {
			this._onreadystatechange = this.onreadystatechange;
		}
		this.onreadystatechange = onReadyStateChangeAugmented;

		return send.apply(this, arguments);
	}

	function onReadyStateChangeAugmented() {
		/* place your function call here */
		opera.postError('HTTP-Anfrage-Status geändert : ' + this.readyState);
		if(this._onreadystatechange) {
			return this._onreadystatechange.apply(this, arguments);
		}
	}

	window.XMLHttpRequest.prototype.open = openAugmented;
	window.XMLHttpRequest.prototype.send = sendAugmented;
})();


Instructions where to put calls to your routines | functions are inside the code.

I hope that helps people who encounter similar problems.

PS: This userJavaScript should not break the execution of the normal XMLHttpRequests, but if you encounter problems, I would like to read about it - not that I could solve them, I am happy that I was able to cobble this together, but may be you or one of the other readers can improve it and feels like posting the solution in the comments.

PPS: You should translate the message texts for the error console to your own language, if you care about that wink

TruthExperimental WOT UserJS update

Comments

DitherDitherSky Sunday, February 19, 2012 12:30:46 AM

The idea is so cool yikes and it's possible to set @include only to fixed sites to avoid hassle. But isn't DOMNodeInserted event listener more appropriate here?

QuHno Sunday, February 19, 2012 7:14:07 PM

I tried it with that too, but DOMNodeInserted fires on almost everything, even on nodes I myself insert after the page has changed, so I was drowned in events and analyzing that was a real PITA lol

How to use Quote function:

  1. Select some text
  2. Click on the Quote link

Write a comment

Comment
(BBcode and HTML is turned off for anonymous user comments.)

If you can't read the words, press the small reload icon.


Smilies