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?

7
  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

  • JCH Optimize does a great job including both combine and optimizing – KlintWeb Jan 12 '18 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 Jan 18 '18 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 Jan 18 '18 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. – jamesgarrett Jan 18 '18 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 Jan 19 '18 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 acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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