Opera et XMLHttpRequest

Le navigateur Opera me surprend souvent par ses implémentations des standards web ; généralement en avance par rapports aux autres constructeurs ; toujours respectueux des dits standards. D'où mon étonnement lorsque j'ai corrigé dans ma librairie javascript un bug qui le touchait et relatif à l'écoute des événements de l'objet XMLHttpRequest...

Dans le document de travail XMLHttpRequest 2, définissant l'objet de requête XMLHttpRequest, il est fait mention de l'interface XMLHttpRequestEventTarget qui étend EventTarget, l'interface DOM mettant à disposition - entre autre - la méthode d'attache d'écouteur d'événement addEventListener ; elle définit par ailleurs les évéments émis : loadstart, progress, abort, error, load, timeout et loadend. On devrait donc s'attendre à pouvoir écrire quelque chose comme ce qui suit(1) :

var request = new XMLHttpRequest();
request.addEventListener('load', function (e) {
    console.log('loaded...');
});
request.send(uri);
Ecoute du chargement d'une ressource par un objet XMLHttpRequest.

En fait, Opera n'a pas (encore) implémenté l'interface EventTarget sur ces objets XMLHttpRequest, ce qui peut d'ailleurs apparaître paradoxal vu que le rédacteur des documents W3C est Anne van Kesteren, employé chez… Opera.

Pour contourner le problème, tout en évitant de modifier le code partout où on utilise XMLHttpRequest, on peut écrire un « encapsuleur » portant un correctif (qui existe déjà le plus souvent, afin de supporter les navigateurs qui ne connaissent pas encore XMLHttpRequest), ce qui donnerait quelque chose du genre :

var XHR = window.XMLHttpRequest.prototype.addEventListener ?
    function () {
        var req = new XMLHttpRequest();
        req.LISTENERS = {};
        req.onreadystatechange = function (e) {
            switch (this.readyState) {
                case 1: 
                    break;
                case 2: 
                    break;
                case 3:
                    if (this.LISTENERS.progress) {
                        this.LISTENERS.progress(e);
                    }
                    break;
                case 4: 
                    if (this.LISTENERS.load) {
                        this.LISTENERS.load(e);
                    }
                break;     
              }
        };
        req.addEventListener = function (event, listener) {
            this.LISTENERS[event] = listener;                
        };
        return req;
    } : function () {
        return new XMLHttpRequest();
    };
Ajout de la méthode addEventListener sur l'objet XMLHttpRequest.
var request = new XHR();
request.addEventListener('load', function (e) {
    console.log('loaded...');
});
request.send(uri);
Utilisation du nouvel objet XHR.

OPERA. XHR (XMLHttpRequest / Ajax) support in Opera Presto 2.10. opera.com

SCHEPERS, Doug ; HÖHRMANN, Björn ; LE HÉGARET, Philippe, et al.. Document Object Model (DOM) Level 3 Events Specification. W3C, . 4.3 Interface EventTarget

VAN KESTEREN, Anne. XMLHttpRequest. W3C,

VAN KESTEREN, Anne. XMLHttpRequest Level 2. W3C,

XMLHttpRequest. Mozilla Developer Network,

Using XMLHttpRequest. Mozilla Developer Network,