Page MenuHomePhabricator

Optimise jQuery.ready by calling it before </body>
Closed, ResolvedPublic

Description

Currently, JavaScript callbacks registered using addOnloadHook() from wikibits.js are (normally) executed just after the page content has been completely parsed. This is achieved by including the following code, returned by Skin::getBottomScripts(), just before the </html> closing tag:

<script type="text/javascript">if (window.runOnloadHook) runOnloadHook();</script>

However, addOnloadHook() is being deprecated in favor of jQuery's $(document).ready(). Callbacks registered using that method normally run as soon as jQuery can determine that the page has been completely parsed. On browsers supporting it, this is done during the DOMContentLoaded event, which should fire only marginally after the call to runOnloadHook(). However, on IE jQuery relies on the readystatechange event, which fires only at a later stage. This can delay the execution of callback scripts and degrade the user experience.

A simple solution would be to call $.ready(), which runs the callbacks registered using $(document).ready(), from bottomscripts just like runOnloadHook() is currently called. This solution is recommended in the comment at http://api.jquery.com/ready/#comment-84865796 which also describes the issue.

In an earlier discussion, some concern had been raised that the DOM might not be completely loaded at that point yet. I haven't found an authoritative source on that, but I'd like to note that:

  1. MediaWiki site/user script authors have been doing extensive DOM manipulation in addOnloadHook() callbacks for many years now. I'm not aware of anyone ever reporting issues with it.
  1. I've been personally testing this by calling addOnloadHook($.ready) from [[commons:User:Ilmari_Karonen/vector.js]] since April. So far I have experienced no problems with this whatsoever, despite being an active user and script author on that site (although, admittedly, I haven't gone out of my way to conduct extensive cross-browser testing with it).

(Ps. Apparently ResourceLoader moves a lot of JS/CSS that used to go in <head> into bottomscripts. Presumably the call to $.ready() should occur in a separate <script> element at the very end of the scripts.)


Version: 1.17.x
Severity: enhancement

Details

Reference
bz25860

Event Timeline

bzimport raised the priority of this task from to High.Nov 21 2014, 11:16 PM
bzimport set Reference to bz25860.

I will support this, cautiously, but we need to keep an eye on the lower browsers that we are sending JS to (like IE6 for instance).

Is this superseeded by the ResourceLoader?

(In reply to comment #2)

Is this superseeded by the ResourceLoader?

No, it isn't.

(In reply to comment #4)

Maybe related: Gerrit change #61494

Bug 34542 and bug 47457 were related to that patch.

Ilmari / Trevor: Is this still an issue after that Gerrit change got merged in April 2013.