Question

It seems like very common practice to load scripts at the end of a page now / not in the <head>. The problem is when you need to run some jQuery inline in the body due to template structure, variable access, etc., depending on project.

What is the easiest way (preferably vanilla JS) to queue a function to run after jQuery becomes defined later?

There are lots of complicated JS libraries for handling this and I'd prefer a brain dead / understandable process with zero documentation.

Is there an accepted "one liner" that's useful without loads of code?

Here's round 1 with CoffeeScript that works, just to show I'm putting some effort into answering it myself. Next up I will convert this to JS and try to come up with a simpler api.

class root.DeferUntil
    constructor: ({@deferredFunction, @deferralCheck} = {}) ->
        @interval = setInterval @executeIfLoaded, 500

    executeIfLoaded: =>
        if not @executed and @deferralCheck()
            @deferredFunction()
            clearInterval @interval

new DeferUntil
     deferredFunction: ->
         console.log "Hi, #{$} shouldn't raise errors"
     deferralCheck: ->
         $ != undefined
Was it helpful?

Solution 2

If you're controlling the page layout, then it probably goes without saying that the simplest way is to put the function call to your function after jQuery at the end of your page.


If you can put some code after the jQuery script that you're waiting for, but want that code to be generic, not specifically tied to your other code, then you could put something like this.

Put this before your code:

var readyFns = [];
function runReady() {
    for (var i = 0; i < readyFns.length; i++) {
        readyFns[i]();
    }
}

function addReady(fn) {
    readyFns.push(fn);
}

Put this AFTER the jQuery script tag:

$(document).ready(runReady);

The, anywhere in your code (after the first block of code, but before jQuery), you can just schedule any read function with this:

addReady(function() {
    // put your code here
});

If you really want something hands-off, you can poll for when jQuery is loaded.

(function() {
    function check() {
        if (window.jQuery) {
            // put your jQuery code here
        } else {
            setTimeout(check, 1);
        }
    }
    setTimeout(check, 1);

})();

What makes anything else difficult is that what you want to do is to wait for a script tag to load that isn't parsed yet. Because it's not parsed yet, you can't install any event handlers on it.

OTHER TIPS

I've used something like this in the past:

window.Preload = $.extend [],
  run: (e) -> e(window.$)
  load: ->
    @shift = @run
    @push = @run
    @run(func) for func in @
    @splice(0, @length)

Then, you can just push your functions into the Preload array:

Preload.push ($) ->
  # Do something with jQuery here

And after jQuery is loaded:

Preload.load()

That'll execute all your preload functions, and if load() has already been called, functions pushed onto Preload just get executed immediately. This pattern is useful for all kinds of asynchronous load behavior, where you want to run some functions only after a precondition has been met, without having to necessarily know if your precondition is met yet or not.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top