Force execution order of jQuery events

8

Assuming a page that has multiple events being associated via jQuery. For example, in a certain section, I have:

$().ready(function() {
    foo();
});

And more ahead I have:

$().ready(function() {
    bar();
});

And several more lines below ...

$().ready(function() {
    VoceJahEntendeuAIdeia();
});

Now supposing I want to force the order of execution of the events. Is there any way to do bar(); rotate before foo(); , which does not necessarily involve changing the two position or modifying the jQuery code?

The reason is that I'm dealing with code injected into the application through the load and ready events of jQuery, for components of a framework I'm using. Such a framework necessarily injects its last code into the page load, but I really need my code to run last. And I find the use of setTimeout / setInterval inelegant.

    
asked by anonymous 03.02.2014 / 23:18

3 answers

7

If you can not modify the code in any way, my only suggestion is to do a " monkey patch " in the jQuery.fn.ready function, to specify an execution order. Put this code before from all other (but after ) of inserting the script with jQuery itself, of course):

var ordem = [0,2,3,1]; // Especifica a ordem desejada
var iniciadores = []; // Acumula os iniciadores
$(document).ready(function() {
    // Executa os iniciadores na ordem
    for ( var i = 0 ; i < ordem.length ; i++ ) {
        var x = iniciadores[ordem[i]];
        x[0].apply(x[1], x[2]);
    }
    // Remove o "monkey patch"
    $.fn.ready = oldReady;
});

var oldReady = $.fn.ready; // Guarda o ready original
// Monkey patch
$.fn.ready = function(fn) {
    if ( this[0] == document ) // Se for no document...
        iniciadores.push([fn, this, arguments]); // não execute, acumule
    else
        return oldReady.apply(this, arguments); // Senão execute
}

Example in jsFiddle .

    
04.02.2014 / 00:48
1

There really is not a way to do this, but if it helps, you can delegate a load event to run your script. So it will only run when all the components of the page, including what was last inserted, are loaded.

    
03.02.2014 / 23:31
1

A simple way, but not very elegant in the way it is:

$('#teste').on('click',     function(e){ console.log( 1, e.type ); }); // 3
$('#teste').on('mousedown', function(e){ console.log( 2, e.type ); }); // 1
$('#teste').on('mouseup',   function(e){ console.log( 3, e.type ); }); // 2
$('#teste').on('click',     function(e){ console.log( 4, e.type ); }); // 4

// Alterando a ordem

// Salva eventos originais de click
var eventosOriginais = jQuery.extend( true, {}, $._data($("#teste")[0], "events").click );
// Apaga os eventos
$('#teste').off('click')
// readiciona os eventos na ordem desejada
$('#teste').on('click', function(e){ 
    eventosOriginais[1].handler(e);
    eventosOriginais[0].handler(e);
})

With some work, you automate the re-bind of events, to the way you want to

functional sample in jsfiddle

Another option, just to solve your problem is to look for some other event that is normally triggered before, as in the example, mousedown and mouseup click

    
04.02.2014 / 02:15