Back in the early Joomla 3 days we used to send data to the frontend JavaScript code using inline JavaScript fragments. For example:
JFactory::getDocument()->addScriptDeclaration(<<<JS var comExampleSomething = "{$foobar}"; JS );
On the client side (JavaScript) you'd just use this JavaScript variable.
This is bad for a number of reasons. To begin with, the inline
script declaration must definitely be parsed before any other code —
including JavaScript files — which make use of it. Back when all scripts
were loaded in the document's <head>
that was a given.
However, this code broke spectacularly when met with any plugin or third
party solution (such as CloudFlare RocketLoader) which moved the scripts
at the bottom of the HTML <body>
or lazy-loaded them.
There was no guaranteed script execution anymore.
The variable being passed (in our example, $foobar
)
would have to be properly escaped to make it valid JavaScript or the
client-side could break or, worse, we'd introduce a security
vulnerability!
Moreover, this solution pollutes the JavaScript global scope and slows down the page as the browser has to stop parsing the DOM and rendering the page to evaluate the JavaScript.
Ever since Joomla 3.5 you had the option to instead push script options through the document:
\Joomla\CMS\Factory::getDocument()->addScriptOptions( 'com_example', [ 'foo' => $foobar, 'bar' => SOME_CONSTANT, ] );
This embeds a JSON document into the HTML which does not need to be parsed by the browser as JavaScript. Instead, when the core JavaScript loads it will parse it and make it available to our client-side code:
var comExampleOptions = Joomla.getOptions('com_example'); var distance = comExampleOptions.foo * comExampleOptions.bar;
But how can we be sure that our code loads after the core Joomla
JavaScript? Well, this is trivial in Joomla 4 and later by using the WebAssetManager and adding
core
as a dependency. We also need to set our script to have
the option "defer": true
in our
joomla.asset.json
file so it loads deferred, i.e.
after the browser parses the DOM — just like the core JavaScript does.
This way we can be sure that our file executes after
Joomla.getOptions
is available in JavaScript and we no longer
need to add special code to execute our code after the page has finished
loading; both conditions are guaranteed.