Vanilla 1 is no longer supported or maintained. If you need a copy, you can get it here.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Scripts at bottom of page?

edited December 2008 in Vanilla 1.0 Help
How can I move my scripts to the bottom of the page for performance reasons? My SyntaxHighlighter extension loads some heavy JavaScript, and I'd really like to delegate all JS to just before </body>. How can I do this? I tried moving the script output to another part of the template (page_bottom, if I remember the name correctly) but this only resulted in errors/exceptions.

Comments

  • The location should not be chosen for performance reasons. The head or body should be chosen depending on whether you need the JS to run before or after the page is rendered. If you are using jQuery, you can use that to execute the JS after the page is rendered, while still loading it in the head. It is good to have it loaded early, so it is available to run immediately the page is displayed, otherwise you will get a delay in the formatting while the JS is loaded up from the server.

    -- Jason
  • edited December 2008
    No, it is not smart to load JS before HTML because the page will not load until the ~300kb of scripts have loaded. This is common knowledge. Loading JS and running JS are two very different things.
  • It is not smart to load 300kb of scripts either. I thought that was also common knowledge.
  • edited December 2008
    How helpful. Guess I'll figure this out myself. My extension actually loads about 60kb, but like I said, JS at the bottom is common sense. I'm surprised that this software does not support such placement, but I'll find a way.
  • edited December 2008
    There's a couple ways you can go about this...

    To add a script to the very bottom of the page (just before </body>), you need to attach to this delegate:$Context->AddToDelegate('PageEnd', 'PreRender', 'YourFunctionHere');
    In the function YourFunctionHere all you have to do is echo the HTML to inject your script:function YourFunctionHere(&$PageEnd) { echo '<script type="text/javascript" src="js/longscript.js" />'."\n"; }
    That's it for method 1. Very simple and it won't break when upgrading.

    To move all scripts to the bottom (not recommended, but easily possible), you need to modify two templates in the themes/ folder. Here's a diff of what you need to do:Index: themes/head.php =================================================================== --- themes/head.php (revision 773) +++ themes/head.php (working copy) @@ -18,14 +18,6 @@ <link rel="stylesheet" type="text/css" href="'.$StyleSheet['Sheet'].'"'.($StyleSheet['Media'] == ''?'':' media="'.$StyleSheet['Media'].'"').' />'; } } - if (is_array($this->Scripts)) { - $ScriptCount = count($this->Scripts); - $i = 0; - for ($i = 0; $i < $ScriptCount; $i++) { - $HeadString .= ' - <script type="text/javascript" src="'.$this->Scripts[$i].'"></script>'; - } - } if (is_array($this->Strings)) { $StringCount = count($this->Strings); Index: themes/page_end.php =================================================================== --- themes/page_end.php (revision 773) +++ themes/page_end.php (working copy) @@ -1,6 +1,13 @@ <?php // Note: This file is included from the library/Framework/Framework.Control.PageEnd.php class. +if (is_array($GLOBALS['Head']->Scripts)) { + $ScriptCount = count($GLOBALS['Head']->Scripts); + $i = 0; + for ($i = 0; $i < $ScriptCount; $i++) { + echo '<script type="text/javascript" src="'.$GLOBALS['Head']->Scripts[$i].'"></script>'."\n"; + } +} echo '</body> </html>'; ?> \ No newline at end of file
    Honestly though, this is a BAD idea. The best way to accomplish what you want is to add the delegate.

    Keep in mind that as browsers slowly adopt multi-threading for JS, adding scripts to the bottom of your page will become bad practice; more so than it is now.

    Update: I just realized that $this->Scripts is not in the proper context so I changed it to $GLOBALS['Head']->Scripts
  • RIght now it's definitely a best practice simply because the first thing to load on a page should be HTML content. Thanks for the advice, I'll use this on my website.
  • Hold on. I'm looking over my extension again, and I use $Head->AddScript() to inject my scripts. There's no way to send AddScript to the footer? Keep in mind that these are not changes for one site, but rather for an extension I've contributed. I don't want to make footer-loading the default, but it really should be an option.
  • When you're creating an extension, the best way to keep it as unobtrusive as possible is to add your logic through Delegates. Expecting users of your extension to modify their theme files will be a hassle, especially if they're not using the default Vanilla theme.

    So the first option in my previous post should be your solution.
This discussion has been closed.