0.2 #permalink deferred, asap.js, minimal.js, and loadJS
With speed being a primary concern, we don't allow javascript execution to block page loading. It's entirely possible to do anything you're used to, but it could take a little more work. For example, you can't assume that you have access to jQuery in the head or at any point in the body of your page, so putting
<script type="text/javascript">$(window).onload(function(){//etc});</script>
in your head
or something like
<script type="text/javascript">$('.clazz').hide();<script>
in your body
will not work.
Instead, the deferred
array, asap.js
and minimal.js
files, and loadJS
function should help you to get around most of these issues.
deferred
deferred
is a simple javascript array that you can add functions to, and the functions will be executed once jQuery and the rest of our environment is set up. It's defined right up at the top of head.inc
:
<script type="text/javascript">
var deferred = [];
</script>
There are two ways to add functions to the deferred
array. The things added can be functions taking no arguments, so:
<script type="text/javascript">deferred.push(positionSelectors);</script>
<script type="text/javascript">deferred.push(function(){$(window).onload(function(){//etc});});</script>
or you can add an array where the first element is a string matching the name of the function, and the remaining elements are arguments to be passed to the function:
deferred.push(["loadJS","/v2/js/modules/tile.js"])
deferred.push(["gg.img.loadBg","hero","/img/banners/hero_nonprofits","jpg"])
asap.js and minimal.js
/v2/js/asap.js
and /v2/js/minimal.js
are the (only!) scripts that are run on every page on our site. asap.js
is run (asynchronously) quite early in the head
, and minimal.js
is run once the page has loaded. asap.js
contains functions that absolutely must be run early in the pageload, such as the Optimizely snippet (to remove the undesirable "flash"), and code to set the refcode and conversion code (to give us the best chance possible of tracking people if they navigate away quickly). This is also where deferred
and the top-level gg
object are defined, so that pages have access to these variables. Because these scripts are run on every pageload, we need to be really vigilant to make sure everything in there needs to be in there.
loadJS
This is a tiny function (see the documentation here) that allows us to load scripts sequentially and asynchronously. The function takes two arguments: the first is the source of the script to load, and the second is the callback function to execute once it's loaded. It's being used to load minimal.js
, since it (currently) requires jQuery, so first we load jQuery, then load minimal.js
in the callback.
loadJS("/v2/js/deps/jquery-1.12.2.min.js", function() {
loadJS("/v2/js/minimal.js");
});
If you need to load a number of scripts that don't directly depend on each other, you can pass an array of scripts to loadJS. Note that each script is loaded
asynchronously, so there is no gurantee of execution order. But this can be useful if your page relies on a number of 3rd party scripts (say in PE or an admin console)
that do not directly rely on each other. The following example show loading 5 scripts, and then calling an init function. Although the 5 indicated
scripts may load (and execute) in any order, the init
function will not get called until after all scripts are loaded. Note that the init
function
passed as a separate argument to loadJS
.
loadJS([
"/javascript/jquery-ui/1.11.1/jquery-ui.js",
"/javascript/jquery/jquery.blockUI-2.6.6.js",
"/javascript/jquery/jquery.form.js",
"/v2/js/deps/jquery.tablesorter-v2.45.5.combined.min.js",
"/v2/js/admin/checkentry/edit-batch.js"
],
init);
Or, to do things with deferred
:
deferred.push([
"loadJS", [
"/javascript/jquery-ui/1.11.1/jquery-ui.js",
"/javascript/jquery/jquery.blockUI-2.6.6.js",
"/javascript/jquery/jquery.form.js",
"/v2/js/deps/jquery.tablesorter-v2.45.5.combined.min.js",
"/v2/js/admin/checkentry/edit-batch.js"
],
init
]);
If you need to include external javascript, you can include it in the head
or in the foot_scripts
apache variable using the async
parameter:
<!--#set var="foot_scripts" value='
<script src="/path/to/myScript.js" async></script>
'-->
Or you can load it with loadJS
. But note that your statement will be processed before loadJS
has been defined, so you'll want to wrap it in a function and pass that to deferred
:
deferred.push(
["loadJS",'/path/to/myScript.js',function(){//optional callback here}];
);
Markup
Markup:
styleguide/styleguide.less
, line 47