-1

I want to add a javascript file to very end of footer.php with an wordpress plugin. i tried it using 'add_action' Hook. But this hook is adding javascript nearby </body> tag.

add_action('wp_footer', 'my_fucntion()');

How can i push my javascript to very end of footer.php

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
mohit
  • 290
  • 1
  • 6
  • 19
  • no its not actually i want my javascript after ` – mohit Jan 31 '14 at 12:22
  • 2
    That would be invalid. An HTML DOM consists of a single, root node, which is the `` tag. Tags aren't allowed outside of the actual HTML (which makes sense if you think about it). Again: do some research [script tags go in the head or body tags](http://stackoverflow.com/questions/3037725/is-it-wrong-to-place-the-script-tag-after-the-body-tag) for a reason. It only took me a minute to google-search this, and come up with these links – Elias Van Ootegem Jan 31 '14 at 12:24
  • @EliasVanOotegem yes i know that but i want to alter some values with this javascript. – mohit Jan 31 '14 at 12:26
  • 1
    Use a bloody event `onload`, `onreadystatechange`... allow you to execute the JS only when the things that you want to change are there, and ready to be manipulated – Elias Van Ootegem Jan 31 '14 at 12:27
  • @EliasVanOotegem This javascript changes normal links to affiliate links. Other networks are using same technology. if an affiliate put those javascript from two different networks then the javascript at the end of the page will win. Thats why i want my javascript at very end of the page – mohit Jan 31 '14 at 12:30
  • That sounds very obtrusive and hack-ish o.O – Cerbrus Jan 31 '14 at 12:34
  • @Cerbrus no its not hack-ish. Now affiliates have to add affiliates links manually. with this plugin they dont have to add link manually this javascript will detect domains and then will alter the link with affiliate links – mohit Jan 31 '14 at 12:36
  • 1
    *"javascript at the end of the page will win"* <-- That's a hack. – Cerbrus Jan 31 '14 at 12:38
  • @mohit: TMTOWTDI, and your current approach sounds like an ugly hack. I'm not saying that what you're doing is bad or hacky, but the way you're going about your business certainly is. Besides: JS at the end of the page doesn't get executed if previous scripts contain an error – Elias Van Ootegem Jan 31 '14 at 12:40
  • @EliasVanOotegem Whats the Other way ? – mohit Jan 31 '14 at 12:42
  • Besides, what you (apparently) really want is your JavaScript to be the **last** to execute. There is no way to guarantee that. (aside from running it in a page unload event, but that'd be pointless) – Cerbrus Jan 31 '14 at 12:44
  • @mohit: The right question is: _How many other ways_ but basically: you have no _real_ control over the queue, but there are some tricks, I'll post a simple one as answer – Elias Van Ootegem Jan 31 '14 at 12:44
  • so there is no way to do that right ? – mohit Jan 31 '14 at 12:48
  • @EliasVanOotegem ok i am waiting :) – mohit Jan 31 '14 at 12:50

1 Answers1

1

Update
There's a better way, the one below should work, but this one should be safer, still (and it's easier, IMO).
Given that JS is single-threaded, an event will push the handler to the back of the queue anyway, so if your onload handler ends up being called prior to another handler, dispatching a new event, that calls a handler that actually does the work you want/need to do is probably your best bet:

window.addEventListener('load', function rmMe()
{
    var handler = function()
    {
        window.removeEventListener('click', handler, false);//remove this listener, too
        var i, links = document.querySelectorAll('a');
        for (i=0;i<links.length;++i)
        {
            //do stuff with links
        }
    };
    window.removeEventListener('load', rmMe, false);
    window.addEventListener('click', handler, false);//bind new listener
    window.dispatchEvent(new Event('click'));//calls handler, last handler in queue
},false);

That might be your best bet...


After those endless comments, it would apear that you're looking for a way to guarantee that your JS gets executed after the page has loaded, and all other possible onload event handlers have been called.
The simple answer is: you can't. Not really. JS's event loop is beyond your control, but there are a few tricks that do work in most cases:

  1. Add your script to the bottom of the body tag
  2. Bind your event listener but wrap it in a setTimeout with zero or 1 ms delay
  3. to be safe, let the event handler set another timeout that actually calls the function that does the work, this time, use a timeout that allows for a queued handler to be called. This is optional, because the queue is probably empty already
  4. important make sure (or hope) that other handlers don't call stopPropagation on the event: this'll result in your listener not getting called. That's why the first method is preferable: it pushes a new handler to the back of the queue, allowing you to bind your listener first.

Code example:

setTimeout(function()
{
    window.onload = function()
    {
        var handler = function()
        {
            var i, links = document.querySelectorAll('a');
            for (i=0;i<links.length;++i)
            {
                //do stuff with links
            }
        };
        return function()
        {//fake, initial handler
            setTimeout(handler, 40);//optional, return handler; should suffice
        };
    };
},1);

That's all there is too it. This code, to be clear, goes here in the DOM:

        <script>
            //code here
        </script>
    </body>
</html>

This is not 100% reliable, but most browsers queue event handlers as they are being bound:

window.addEventListener('load', function(){}, false);//likely to be called first
window.addEventListener('load', function(){}, false);//likely to be called second

and so on. Not sure about this, but I wouldn't be surprised if listeners that are bound using the window.addEventListener are more likely to be appended to the end of the queue, as the addEventListener call may cause overhead. Probably use:

setTimeout(function()
{
    window.addEventListener('load', function tmpLoad()
    {
        var handler = function()
        {
            var i, links = document.querySelectorAll('a');
            for (i=0;i<links.length;++i)
            {
                //do stuff with links
            }
        };
        return function()
        {//fake, initial handler
            window.removeEventListener('load', tmpLoad, false);//adds overhead and time
            setTimeout(handler, 40);//optional, return handler; should suffice
        };
    },false);
},1);

You could also consider manually dispatching an event, after a timeout, bind a new listener, and then do: window.dispatchEvent(new Event('load')); to call the handler.

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • I was afraid you'd use a `setTimeout()` :P Still, this should work. +1 – Cerbrus Jan 31 '14 at 12:59
  • @Cerbrus: In my last edit, I also hinted at creating your own event chain, dispatching a series of events might also work: a new event gets added to the back of the queue, so using that handler might do the trick, too, no? – Elias Van Ootegem Jan 31 '14 at 13:02
  • That might also work, yea. – Cerbrus Jan 31 '14 at 13:04
  • @mohit: NP, you'll have to work on X-browser issues if you want to support older versions of IE, though. `addEventListener` vs `attachEvent` and all that, but that's your job now. If you're stuck with that, you can always post a follow-up. Also read point 4 (just added), stopPropagation is unlikely on a load event, but _can_ happen – Elias Van Ootegem Jan 31 '14 at 13:12