6

Unfortunatelly I can't register on the joomla forum, so I'll try my best here.
Please help, is there any way to control the order of loaded scripts.

Example: in my template's index.php I do:

$doc->addScript('my/script_a.js');

as the very first addScript(); So I load that script globally for all pages.

Then, in the default.php of my custom component I do:

$doc->addScript('my/script_b.js');

to add additional behaviour for that very component view specifically.

Logically I would assume that the addScripts in the index.php are added to the $doc object first and after that the addScripts in the component view are appended $doc object.
But what I end up with in the head is:

<script src="my/script_b.js"></script>
<script src="my/script_a.js"></script>

This bugs me pretty hard since my/script_a.js performes calculations my/script_b.js depends on, so the order is crucial.

Please, there must be a way to control the order of loading scripts otherwise this feature is pretty much pointless, isn't it?

2 Answers 2

8
  1. The JDocument's addScript method has no options for ordering (eg by priority or something like WP).
  2. There are numerous ways to solve your problem.

First, to understand why what you're doing is causing the problem you need to know the Joomla lifecycle.

  1. Bootstrap Framework & Application
  2. Route
  3. Component
  4. Modules
  5. Template
  6. Render and Respond

So when you call addScript in your template it gets added to the Document after the script added by your component.

Second, to the solutions...

  1. If the script loaded by your template has no dependencies then just write it inline above your

    <jdoc:include type="head" />
    
  2. Custom head tags are loaded after the scripts so in your component don't use addScript, use addCustomTag instead. eg.

    $doc->addCustomTag('<script src="my/script_b.js"></script>');
    
  3. Write a system plugin and in the onAfterRoute method first load your global script and then see if the option in the JInput is your component and then load your component script if it is (or just load it in your component tmpl as you're already doing).

  4. In the template get the head data from the JDocument and rustle it how ever you like.

Further reading:

https://github.com/joomla/joomla-cms/blob/staging/libraries/src/Document/HtmlDocument.php

6
  • JCH Optimize does a great job including both combine and optimizing
    – KlintWeb
    Commented Jan 12, 2018 at 17:33
  • So the problem is that the component gets loaded before the template, so in the JDocument object the scripts added in the component are before the ones added in the template, right? But how difficult can it be to to load the scripts in the JDocument like ¸JDocument
    – antimatter
    Commented Jan 18, 2018 at 10:50
  • I accidentally hit return and now I can't edit that comment anymore. This was the comment I actually wanted to make: So the problem is that the component gets loaded before the template, so in the JDocument object the scripts added in the component are before the ones added in the template, right? But how difficult can it be to to load the scripts in the JDocument like JDocument->scripts->component = []; JDocument->scripts->template = []; and on when it gets jdoc:includ(ed) joomla only needs to make a echo JDocument->scripts->template; echo JDocument->scripts->component;
    – antimatter
    Commented Jan 18, 2018 at 10:58
  • If you're asking whether such an approach is possible now, then the answer is 'no, the jdocument keep any reference regarding which piece of code added which script'. If you're asking something else then I don't know what you're asking. Commented Jan 18, 2018 at 22:05
  • Something like on application start loading JDocument->scripts = new stdClass();. The script loading the component: $scripts = []; foreach(<JDocument added script> as <script>){ array_push($scripts, <script>); } JDocument->scripts->component = $scripts;. The script loading the template: $scripts = []; foreach(<JDocument added script> as <script>){ array_push($scripts, <script>); } JDocument->scripts->template = $scripts;. You end with an object scripts holding the arrays component, template (, modules, etc).
    – antimatter
    Commented Jan 19, 2018 at 18:51
0

Had the same problem and came across your post. I fixed it in my template, works for all Joomla versions up to 3.9.

$doc = JFactory::getDocument();
foreach ($doc->_scripts AS $script => $options) {
    if (strpos($script, 'com_your_component') === false) break;
    $doc->_scripts[$script] = array_shift($doc->_scripts);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.