Force jQuery event execution order

Asked

Viewed 2,418 times

8

Suppose a page has several events being associated via jQuery. For example, in a given section, I have:

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

And further ahead I have:

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

And several lines further down...

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

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

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

  • 3

    A way would be a function of callback to be called after the framework, but without a more concrete idea of how things are happening, it is difficult to provide an adequate solution to the scenario in question. You can add a little more information about the way this code framework is being injected?

3 answers

7


If you cannot modify the code in any way, my only suggestion is to make a "Monkey patch" in function jQuery.fn.ready, to specify an execution order. Enter this code before of all others (but afterward insert 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.

  • 1

    Note: if you think setTimeout Inelegant, this you will find even more... : P But it is an alternative.

  • I don’t find it more inelegant - being well documented, it will make more sense to the next developer than a setTimeout free. Thank you :) (+1)

1

There really isn’t 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 page components, including the last one, are loaded.

  • Just as an observation, really the method .load() jQuery has been deprecated, but you can still use the method .on() to delegate the event.

  • If you do not know how to use it, you can see some examples in this article: http://jquerybrasil.org/delegatndo-e-removendo-eventos-com-on-e-off/

1

A simple but not very elegant way:

$('#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, for the way you want

functional example in jsfiddle

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

  • I did a test, and it seems that this will not work for Document.ready (which is the case with the question). $._data(x, "events") returns undefined for document, document.body and window.

  • I did tests with Document and it didn’t work at all. This solution works only on objects from GIFT, look for some option and add-on

Browser other questions tagged

You are not signed in. Login or sign up in order to post.