Modifier une fonction jQuery native sans l’altérer

Dernièrement, je cherchais à effectuer une action supplémentaire en cas de succès d’un appel Ajax : en effet, dans l’application que je développe, j’ai un contrôleur principal, par lequel passent toutes les requêtes, et qui vérifie si l’utilisateur est bien connecté – dans le cas contraire, il le redirige vers la page de connexion. Mais dans le cas d’une page laissée à l’abandon suffisamment longtemps pour que la session expire, et où l’utilisateur ne recharge pas, mais effectue une action qui appelle le serveur via XMLHttpRequest (Ajax, en gros), eh bien, la redirection ne se faisait pas comme je le voulais.

En effet, les spécifications du W3C indiquent que si l’origine de la source et l’origine de l’URL demandée sont la même, alors le navigateur doit suivre silencieusement la redirection, tout en observant les règles d’évenements s’appliquant aux requêtes de même origine.1

Par conséquent, comme la fonction JavaScript exécutée en retour de mon appel affichait des informations dans un élément de la page, à cause de la redirection, c’était la page de connexion qui se retrouvait dans cet élément. Donc, il me fallait trouver un moyen de rediriger correctement. Et pour cela, j’ai fait ce que Paul Irish appelle du duck punching ! L’idée est tout simplement de redéfinir une fonction de base pour qu’elle renvoie autre chose.

Ici, je court-circuite la méthode jQuery.ajax, en conservant l’ancienne méthode dans une variable :

var _old = $.ajax;

…et aussi l’objet (success) que je vais modifier :

var _oSuccess = options.success; // on conserve la référence de base à l'objet

…en précisant que si je reçois une réponse particulière :

if(response.deconnexion_utilisateur == true)

…alors je fais une action particulière :

location.href = response.url ;
return false;

…sinon on réinjecte l’objet de base :

_oSuccess(response); // on réinjecte l'objet

Dans tous les cas, on lance l’ancienne fonction, avec, peut-être, les nouveaux arguments :

return _old.call(this,options);

Ce qui nous donne au final :

(function($){

    var _old = $.ajax; // on conserve la référence de base à la méthode
    $.ajax = function(options){
        var _oSuccess = options.success; // on conserve la référence de base à l'objet
        options.success = function(response) {
            if(response.deconnexion_utilisateur == true){
                // on redirige vers la connexion
                location.href = response.url ;
                return false;
            }
            else {
                _oSuccess(response); // on réinjecte l'objet
            }
        }
        // on appelle l'ancienne méthode avec les nouveaux arguments
        return _old.call(this,options);
    };

})(jQuery);

  1. If the source origin and the origin of request URL are same origin transparently follow the redirect while observing the same-origin request event rules. Source : http://www.w3.org/TR/XMLHttpRequest/#infrastructure-for-the-send-method  

Laisser une réponse

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax